views:

762

answers:

6
void pushSynonyms (string synline,  char  matrizSinonimos [1024][1024]){


             stringstream synstream(synline);

             vector<int> synsAux;


             int num;

             while (synstream >> num) {synsAux.push_back(num);}


             int index=0;
             while (index<(synsAux.size()-1)){

                   int primerSinonimo=synsAux[index];
                   int segundoSinonimo=synsAux[++index];
                   matrizSinonimos[primerSinonimo][segundoSinonimo]='S';
                   matrizSinonimos [segundoSinonimo][primerSinonimo]='S';

                   }

           }

and the call..

char matrizSinonimos[1024][1024];
     pushSynonyms("1 7", matrizSinonimos)

It's important for me to pass matrizSinonimos by reference.

Edit: took away the & from &matrizSinonimos.

Edit: the runtime error is:

An unhandled win32 exception occurred in program.exe [2488]![alt text][1]
+4  A: 

Arrays are passed as pointers - there's no need to do a pass-by-reference to them. If you declare your function to be:

void pushSynonyms(string synline, char matrizSinonimos[][1024]);

Your changes to the array will persist - arrays are never passed by value.

Harper Shelby
still fails at runtime.
omgzor
I made the edit, though.
omgzor
+1. That should work.
Binary Worrier
When you have matrizSinonimos [1024][1024] in your function parameters ar as a variable inside main(), you allocate 1MB of memory on stack. Stack is usually large, but this is excessive. Please declare the actual array static, and pass a pointer.
Arkadiy
@Arkadiy: I tried: 'char static matrizSinonimos[10][10]; char *pointer = 'And got a compile error of cannot convert char[*][10][10] to char in initialization.
omgzor
Harper, char matrizSinonimos [1024][1024] and char matrizSinonimos [][1024] is the same in parameter lists though. i must misunderstand you.
Johannes Schaub - litb
@dmindreader: char foo[10][10] is not a char*, it's a char**. If you want to pass the array with that syntax, you would declare:void pushSynonyms(string synline, char **matrizSinonimos); . Typically a declaration with a pointer member will accept length parameters per dimension to avoid errors.
Harper Shelby
"char *pointer = " is no good. You really need to learn how multidimentional arrays are represented in C. x[10][10] is not a pointer to char, it's a pointer to array of blocks 10 chars each. Use char ptr[][10] = matrix; "ptr" here is a pointer to undefined number of 10 char blocks.
Arkadiy
(oops, "it's a pointer to array of blocks 10 chars each" should be replaced with "it's an array of blocks 10 chars each")
Arkadiy
A: 

(edit 1) I forgot to answer your actual question. Well: after you've corrected the code to pass the array in the correct way (no incorrect indirection anymore), it seems most probable to me that you did not check you inputs correctly. You read from a stream, save it into a vector, but you never checked whether all the numbers you get there are actually in the correct range. (end edit 1)

First: Using raw arrays may not be what you actually want. There are std::vector, or boost::array. The latter one is compile-time fixed-size array like a raw-array, but provides the C++ collection type-defs and methods, which is practical for generic (read: templatized) code.

And, using those classes there may be less confusion about type-safety, pass by reference, by value, or passing a pointer.

Second: Arrays are passed as pointers, the pointer itself is passed by value.

Third: You should allocate such big objects on the heap. The overhead of the heap-allocation is in such a case insignificant, and it will reduce the chance of running out of stack-space.

Fourth:

void someFunction(int array[10][10]);

really is:

(edit 2) Thanks to the comments:

void someFunction(int** array);

void someFunction(int (*array)[10]);

Hopefully I didn't screw up elsewhere.... (end edit 2)

The type-information to be a 10x10 array is lost. To get what you've probably meant, you need to write:

void someFunction(int (&array)[10][10]);

This way the compiler can check that on the caller side the array is actually a 10x10 array. You can then call the function like this:

int main() {
  int array[10][10] = { 0 };
  someFunction(array);
  return 0;
}
gimpf
void someFunction(int array[10][10]) is really void someFunction(int *(* array)[10]). You can verify this with MSVC or comeau's online C++ compiler.
MSN
you are both wrong. void someFunction(int array[10][10]); is void someFunction(int (*array)[10]); :) gimpf your answer were perfectly right, until you said "void someFunction(int array[10][10]); really is void someFunction(int** array);"
Johannes Schaub - litb
Gar, stupid copy paste error.
MSN
Stupid me. Back to school...
gimpf
+3  A: 

The exception is probably 0xC00000FD, or a stack overflow!

The problem is that you are creating a 1 MB array on the stack, which probably is too big.

MSN

MSN
+4  A: 

What's wrong with it

The code as you have it there - i can't find a bug. The only problem i spot is that if you provide no number at all, then this part will cause harm:

(synsAux.size()-1)

It will subtract one from 0u . That will wrap around, because size() returns an unsigned integer type. You will end up with a very big value, somewhere around 2^16 or 2^32. You should change the whole while condition to

while ((index+1) < synsAux.size())

You can try looking for a bug around the call side. Often it happens there is a buffer overflow or heap corruption somewhere before that, and the program crashes at a later point in the program as a result of that.

The argument and parameter stuff in it

Concerning the array and how it's passed, i think you do it alright. Although, you still pass the array by value. Maybe you already know it, but i will repeat it. You really pass a pointer to the first element of this array:

char matrizSinonimos[1024][1024];

A 2d array really is an array of arrays. The first lement of that array is an array, and a pointer to it is a pointer to an array. In that case, it is

char (*)[1024]

Even though in the parameter list you said that you accept an array of arrays, the compiler, as always, adjusts that and make it a pointer to the first element of such an array. So in reality, your function has the prototype, after the adjustments of the argument types by the compiler are done:

void pushSynonyms (string synline,  char (*matrizSinonimos)[1024]);

Although often suggested, You cannot pass that array as a char**, because the called function needs the size of the inner dimension, to correctly address sub-dimensions at the right offsets. Working with a char** in the called function, and then writing something like matrizSinonimos[0][1], it will try to interpret the first sizeof(char**) characters of that array as a pointer, and will try to dereference a random memory location, then doing that a second time, if it didn't crash in between. Don't do that. It's also not relevant which size you had written in the outer dimension of that array. It rationalized away. Now, it's not really important to pass the array by reference. But if you want to, you have to change the whole thingn to

void pushSynonyms (string synline,  char (&matrizSinonimos)[1024][1024]);

Passing by reference does not pass a pointer to the first element: All sizes of all dimensions are preserved, and the array object itself, rather than a value, is passed.

Johannes Schaub - litb
That's great, but it doesn't exactly address the crash that happens at the function call site.
MSN
i think he should rather focus on the code around the call side. i think the bug could be caused by some buffer overflow or similar.
Johannes Schaub - litb
A: 

try declaring it as:

void pushSynonyms (const string & synline,  char  *matrizSinonimos[1024] )

I believe that will do what you want to do. The way you have it, as others have said, creates a 1MB array on the stack. Also, changing synline from string to const string & eliminates pushing a full string copy onto the stack.

Also, I'd use some sort of class to encapsulate matrizSinonimos. Something like:

class ms
{
    char m_martix[1024][1024];
    public:
    pushSynonyms( const string & synline );
}

then you don't have to pass it at all.

Rob K
A: 

I'm at a loss for what's wrong with the code above, but if you can't get the array syntax to work, you can always do this:

void pushSynonyms (string synline,  char  *matrizSinonimos, int rowsize, int colsize )
{
   // the code below is equivalent to 
   // char c = matrizSinonimos[a][b];
   char c = matrizSinonimos( a*rowsize + b );
   // you could also Assert( a < rowsize && b < colsize );
}

pushSynonyms( "1 7", matrizSinonimos, 1024, 1024 );

You could also replace rowsize and colsize with a #define SYNONYM_ARRAY_DIMENSION 1024 if it's known at compile time, which will make the multiplication step faster.

Crashworks