I want to stick 2D arrays in a 3D array together, first i defined the 3D array in the following way
int ***grid;
grid=new int **[number];
then I want to assign the 2D arrays to the 3D construct
for(i=0;i<number;i++)
grid[i]=rk4tillimpact2dens(...);
with
int** rk4tillimpact2dens(...
...
static int** grid;
grid=new int*[600];
for(i=0;i<600;i++)
grid[i]=new int[600];
memset(grid,0x0,sizeof(grid));
...
return(grid);
}
so far no problem, everything works fine, but when I want to access the 3D array afterwards I get a seg fault. Like that e.g.
printf("%d",grid[1][1][1]);
What is my mistake?
Best,
Hannes
Oh, sorry, it was typo in my question, I did
printf("%d",grid[1][1][1]);
it's not working :(. But even
printf("%d",&grid[1][1][1]);
or
printf("%d",*grid[1][1][1]);
would not work. The strange thing is, that there are no errors unless I try to access the array
First, you discard the very first row of each matrix with that memset (the actual row is leaked). While technically grid[1][1][1] should still be readable, it probably becomes corrupt in some other place.
Can you provide a minimal verifiable example? This is likely to solve your problem.
To clear out the memory allocated for grid, you can't do the whole NxN matrix with one memset, it isn't contiguous memory. Since each row is allocated as a separate memory block, you need to clear them individually.
for(i=0;i<600;i++) {
grid[i]=new int[600];
memset(grid[i], 0, sizeof(int) * 600);
}
The 600 value should be a named constant, and not a hardcoded number.
And grid does not need to be a static variable.
Printing out the address
printf("%p",&grid[1][1][1]);
You are printing the address here. That's why you may not get what you desire to see.
printf("%d",grid[1][1][1]);
This will print the array element.
And to read an input from stdin you will use scanf() which requires you to pass address of an variable.
scanf("%d",&grid[1][1][1]);
Zeroing out the allocated memory
Also you can't get the size of the array using sizeof. SO to initialize with 0 you use memset on the chunks that are allocated at once with a new.
In your case example would be Like 1201ProgramAlarm pointed out
for(int i = 0; i < 600; i++){
...
memset(grid[i],0,sizeof(int)*600);
}
There is another way you can initialise an allocated memory in c++.
grid[i]=new int[600]();
For example:
int** rk4tillimpact2dens(...
...
static int** grid;
grid=new int*[600];
for(i=0;i<600;i++)
grid[i]=new int[600]();
...
return(grid);
}
Do you expect memset(grid,0x0,sizeof(grid)); not to zero the pointer values you've just assigned to grid[0] through to grid[599]? If so, you should test that theory by inspecting the pointer values of grid[0] through to grid[599] before and after that call to memset, to find out what memset does to true (more on that later) arrays.
Your program is dereferencing a null pointer which results directly from that line of code. Typically, a crash can be expected when you attempt to dereference a null pointer, because null pointers don't reference any objects. This explains your observation of a crash, and your observation of the crash disappearing when you comment out that call to memset. You can't expect good things to happen if you try to use the value of something which isn't an object, such as grid[1][... where grid[1] is a pointer consisting entirely of zero bits.
The term 3D array doesn't mean what you think it means, by the way. Arrays in C and C++ are considered to be a single allocation, where-as what your code is producing seems to be multiple allocations, associated in a hierarchical form; you've allocated a tree as opposed to an array, and memset isn't appropriate to zero a tree. Perhaps your experiments could be better guided from this point on by a book regarding algorithms, such as Algorithms in C, parts 1-4 by Robert Sedgewick.
For the meantime, in C, the following will get you a pointer to a 2D array which you can mostly use as though it's a 3D array:
void *make_grid(size_t x, size_t y, size_t z) {
int (*grid)[y][z] = malloc(x * sizeof *grid);
/* XXX: use `grid` as though it's a 3D array here.
* i.e. grid[0][1][2] = 42;
*/
return grid;
}
Assuming make_grid returns something non-null, you can use a single call to memset to zero the entirety of the array pointed to by that function because there's a single call to malloc matching that a single call to memset... Otherwise, if you want to zero a tree, you'll probably want to call memset n times for n items.
In C++, I don't think you'll find many who discourage the use of std::vector in place of arrays. You might want to at least consider that option, as well as the other options you have (such as trees; it seems like you want to use a tree, which is fine because trees have perfectly appropriate usecases that arrays aren't valid for, and you haven't given us enough context to tell which would be most appropriate for you).
Related
consider this code:
double *pi;
double j;
pi = &j;
pi[3] = 5;
I don't understand how is that possible that I can perform the last line here.
I set pi to the reference of j, which is a double variable, and not a double [] variable. so how is this possible that I can perform an array commands on it?
consider this code:
char *c = "abcdefg";
std::cout << &(c[3]) << endl;
the output is "defg". I expected that I will get a reference output because I used &, but instead I got the value of the char * from the cell position to the end. why is that?
You have two separate questions here.
A pointer is sometimes used to point to an array or buffer in memory. Therefore it supports the [] syntax. In this case, using pi[x] where x is not 0 is invalid as you are not pointing to an array or buffer.
Streams have an overload for char pointers to treat them as a C-style string, and not output their address. That is what is happening in your second case. Try std::cout << static_cast<const void *>(&(c[3])) << endl;
Pointers and arrays go hand in hand in C (sort of...)
pi[3] is the same as *(pi + 3). In your code however this leads to Undefined Behavior as you create a pointer outside an object bounds.
Also be careful as * and & are different operators depending on in which kind of expression the appear.
That is undefined behavior. C++ allows you to do things you ought not to.
There are special rules for char*, because it is often used as the beginning of a string. If pass a char* to cout, it will print whatever that points to as characters, and stop when it reaches a '\0'.
Ok, so a few main things here:
A pointer is what it is, it points to a location in the memory. So therefore, a pointer can be an array if you whish.
If you are working with pointers (dangerous at times), this complicates things. You are writing on p, which is a pointer to a memory location. So, even though you have not allocated the memory, you can access the memory as an array and write it. But this gives us the question you are asking. How can this be? well, the simple answer is that you are accessing a zone of memory where the variable you have created has absolutely no control, so you could possibly be stepping on another variable (if you have others) or simply just writting on memory that has not been used yet.
I dont't understand what you are asking in the second question, maybe you could explain a little more? Thanks.
The last line of this code...
double *pi;
double j;
pi = &j;
pi[3] = 5;
... is the syntactic equivalent to (pi + 3) = 5. There is no difference in how a compiler views a double[] variable and a double variable.
Although the above code will compile, it will cause a memory error. Here is safe code that illustrates the same concepts...
double *pi = new double[5]; // allocate 5 places of int in heap
double j;
pi[3] = 5; // give 4th place a value of 5
delete pi; // erase allocated memory
pi = &j; // now get pi to point to a different memory location
I don't understand how is that possible that I can perform the last
line here. I set pi to the reference of j
Actually, you're setting your pointer pi, to point to the memory address of j.
When you do pi[3], you're using a non-array variable as an array. While valid c++, it is inherently dangerous. You run the risk of overwriting the memory of other variables, or even access memory outside your process, which will result in the operating system killing your program.
When that's said, pi[3] means you're saying "give me the slot third down from the memory location of pi". So you're not touching pi itself, but an offset.
If you want to use arrays, declare them as such:
double pi[5]; //This means 5 doubles arrayed aside each other, hence the term "array".
Appropos arrays, in c++ it's usually better to not use raw arrays, instead use vectors(there are other types of containers):
vector<double> container;
container.push(5.25); //"push" means you add a variable to the vector.
Unlike raw arrays, a container such as a vector, will keep it's size internally, so if you've put 5 doubles in it, you can call container.size(), which will return 5. Useful in for loops and the like.
About your second question, you're effectively returning a reference to a substring of your "abcdefg" string.
&([3]) means "give me a string, starting from the d". Since c-style strings(which is what char* is called) add an extra NULL at the end, any piece of code that takes these as arguments(such as cout) will keep reading memory until they stumble upon the NULL(aka a 0). The NULL terminates the string, meaning it marks the end of the data.
Appropos, c-style strings are the only datatype that behaves like an array, without actually being one. This also means they are dangerous. Personally I've never had any need to use one. I recommend using modern strings instead. These newer, c++ specific variables are both safe to use, as well as easier to use. Like vectors, they are containers, they keep track of their size, and they resize automatically. Observe:
string test = "abcdefg";
cout<<test.size()<<endl;//prints 7, the number of characters in the array.
test.append("hijklmno");//appends the string, AND updates the size, so subsequent calls will now return 15.
In Qt, I have a 3-D int-array (say ID[x][y][z]) which I need to set back to 0 during computation.
Is there an efficient way to do it without using a loop?
I need the reinitialization because I am running a specific algorithm with a simple cost-function to get an estimation for the following more detailed computation, and I want to use the same data structure. Simply overwriting the array is not an option, because the algorithm reads and checks entries before writing them.
Sooner or later there's going to be a loop, but you can delegate it to another and more optimized function.
Also, if the "3D array" is really an array of arrays of arrays of some basic type (like int or char), then all the memory is contiguous so you can use a single function call to clear all of the memory in one single call.
Now which function to use; In C++ there are basically two functions you can use: The old C memset function, and the C++ std::fill function. Both should work fine, with proper casting and size, to set all of the data to a specific value.
Under the hood it will (almost) always be a loop. Don't worry, a loop without branches is quite efficient.
If you go for more readable, you can use a function like memset or std::fill which hides the loop.
Have a look at the answers to this question: What's the safe way to fill multidimensional array using std::fill?
The users #JoachimPileborg and #GeorgSchölly have already explained in their answers which functions can be used to reinitialize an array. However, I'd like to add some sample code and explain a difference between std::fill() and memset().
I assume that you want to (re)initialize your array with 0. In this case you can do it as shown in the following code:
#include <xutility> // For std::fill().
int main(int argc, char* argv[])
{
const int x = 2;
const int y = 3;
const int z = 5;
const int arraySize = x * y * z;
// Initialize array with 0.
int ID[x][y][z] = {};
// Use the array...
// Either reinitialize array with 0 using std::fill()...
std::fill(&ID[0][0][0], &ID[0][0][0] + arraySize, 0);
// ...or reinitialize array with 0 using memset().
memset(&ID[0][0][0], 0, sizeof(ID));
// Reuse the array...
return 0;
}
However, if you want to initialize your array with another value (for example, 1), then you have to be aware of a crucial difference between std::fill() and memset(): The function std::fill() sets each element of your array to the specified value. The function memset(), in contrast, sets each byte your array to the specified value. This is why memset() takes the array size as number of bytes (sizeof(ID)).
If you initialize your array with 0, this difference doesn't cause a problem.
But, if you want to initialize each element of your array with a non-zero value, then you have to use std::fill(), because memset() will yield the wrong result.
Let's assume you want to set all elements of your array to 1, then the following line of code will yield the expected result:
std::fill(&ID[0][0][0], &ID[0][0][0] + arraySize, 1);
However, if you use memset() in the following way, then you get a different result:
memset(&ID[0][0][0], 1, sizeof(ID));
As explained above, this line of code sets every byte to 1. Therefore, each integer element of your array will be set to 16843009, because this equals the hexadecimal value 0x01010101.
I have a multidimensional array (a representation of a matrix). I need to zero out, not the entire array, but a section of it. What's the best method of doing this? I tried using memset, but it just gives me a typecast error.
Example
_matrix[row][column] = memset(
_matrix[row][column],
0,
sizeof(_matrix[row][column])
);
Declaration
float** _matrix = new float*[NUM_ROWS][NUM_COL];
The first parameter to memset() is the address of the location to zero. So:
memset(&_matrix[row][column], ...)
However, in your case the following would be far more straightforward:
_matrix[row][column] = 0.0;
This is tagged as C++ yet you're not really doing any C++. Why not just do that? Avoid all the lower level memset and direct array nonsense.
I certainly think you should take some of the previous advice and really learn the underlying C, memory access, etc., but in C++ this could simply be avoided.
A quick line of code to get you on your way:
typedef std::vector<std::vector<int> > Array2D;
I have two character array of size 100 (char array1[100], char array2[100]). Now i just want to check whether anybody is accessing array beyond the limit or not. Its necessary because suppose allocated memory for array1 and array2 are consecutive means as the array1 finish then array2 starts. Now if anyone write: array1[101], conceptually its wrong but compiler will give warning but will not crash. So How can i detect this problems and solve it?
Update 1:
I already have a code of line 15,000. And for that code i have to check this condition and i can invoke my functions but cannot change the written code. Please suggest me according to this.
Most modern languages will detect this and prevent it from happening. C and its derivatives don't detect this, and basically can't detect this, because of the numerous ways you can access the memory, including bare pointers. If you can restrict the way you access the memory, then you can possibly use a function or something to check your access.
My initial response to this would be to wrap the access to these arrays in a function or method and send the index as a parameter. If the index is out of bounds, raise an exception or report the error in some other way.
EDIT:
This is of course a run-time prevention. Don't know how you would check this at compile time if the compiler cannot checkt this for you. Also, as Kolky has already pointed out, it'd be easier to answer this if we know which language you are using.
If you are using C++ rather than C there any reason you can't use std::vector? That will give you bounds checking if the user goes outside your range. Am I missing something here?
Wouldn't it be sensible to prevent the user having direct access to the collections in the first place?
If you use boost::array or similar you will get an exception range_error if array bounds are overstepped. http://www.boost.org/doc/libs/1_44_0/doc/html/boost/array.html. Boost is fabulous.
In C/C++, there is no general solution. You can't do it at compile time since there are too many ways to change memory in C. Example:
char * ptr = &array2;
ptr = foo(ptr); // ptr --;
ptr now contains a valid address but the address is outside of array2. This can be a bug or what you want. C can't know (there is no way to say "I want it so" in C), so the compiler can't check it. Sililarily:
char * array2 = malloc(100);
How should the C compiler know that you are treating the memory as a char array and would like a warning when you write &array2[100]?
Therefore, most solutions use "mungwalls", i.e. when you call malloc(), they will actually allocate 16/32 bytes more than you ask for:
malloc(size) {
mungwall_size = 16;
ptr = real_malloc(size + mungwall_size*2);
createMungwall(ptr, mungwall_size);
createMungwall(ptr+size, mungwall_size);
return ptr+size;
}
in free() it will check that 16 bytes before and after the allocated memory area haven't been touched (i.e. that the mungwall pattern is still intact). While not perfect, it makes your program crash earlier (and hopefully closer to the bug).
You could also use special CPU commands to check all memory accesses but this approach would make your program 100 to 1 million times slower than it is now.
Therefore, languages after C don't allow pointers which means "array" is a basic type which has a size. Now, you can check every array access with a simple compare.
If you want to write code in C which is save, you must emulate this. Create an array type, never use pointers or char * for strings. It means you must convert your data type all the time (because all library functions use const char * for strings) but it makes your code safer.
Languages do age. C is now 40 years old and our knowledge has moved on. It's still used in a lot of places but it shouldn't be the first choice anymore. The same applies (to a lesser extend) to C++ because it suffers from the same fundamental flaws of C (even though you now have libraries and frameworks which work around many of them).
If you're in C++ you can write a quick wrapper class.
template<typename T, int size> class my_array_wrapper {
T contents[size];
public:
T& operator[](int index) {
if (index >= size)
throw std::runtime_error("Attempted to access outside array bounds!");
if (index < 0)
throw std::runtime_error("Attempted to access outside array bounds!");
return contents[index];
}
const T& operator[](int index) const {
if (index >= size)
throw std::runtime_error("Attempted to access outside array bounds!");
if (index < 0)
throw std::runtime_error("Attempted to access outside array bounds!");
return contents[index];
}
operator T*() {
return contents;
}
operator const T*() const {
return contents;
}
};
my_array_wrapper<char, 100> array1;
array1[101]; // exception
Problem solved, although if you access through the pointer decay there will be no bounds checking. You could use the boost::array pre-provided solution.
If you ran a static analyser (i.e. cppcheck) against your code it would give you a bounds error
http://en.wikipedia.org/wiki/User:Exuwon/Cppcheck#Bounds_checking
to solve it... you'd be better off using a container of some sorts (i.e. std::vector) or writing a wrapper
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]
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.
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.
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.
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.
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.
(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;
}