I wrote a collection of codes to solve some physical problems. Unfortunately I cannot show the whole of the codes (they are too long and belong to a private project), but roughly, structure of my program is
double **array1; // declared globally
double **array2; // because there are a lot of functions using array1 & 2
main{
double x;
fscanf(input); // reading an input file
fclose(input); // input file have information about dimension of array
// and step to do different calculation
array = *calloc(~);
array[i] = calloc(~); // making 2d array with dimension from input file
for(i=0;i<large number;i++){
// (doing physical calculation using array1 and array2);
if(i==some step from input file){
// (calculation using array2)
x = array1[k][0]-array1[l][0] ... // !!SEGFAULT!!
}
}
The problem is that regardless of the dimensions of array or any other variables included in the input file, when the program approaches !!SEGFAULT!! region, it produces segmentation fault (using gdb...). "Some step" can be 1, 10, 100, ..., and I tried several tests varying the contents of input files but the program produces segfault only at that region. Valgrind says there is no memory leakage.
One thing strange is that at the beginning of the program, gdb says the address of array1 is (double **) 0x68e410, and this does not change until the program reaches the problematic point. At that point the address of array1 changes to (double **) 0x3ff223bf06cdec4d and I cannot access any of elements of array1.
If I set "some step" to be very large I may avoid the segfault problem but this is not the solution and contaminates the calculation procedure of our project... What is the origin of this problem?
Given the scant information...
these two lines are the root of the problem.
array = *calloc(~);
array[i] = calloc(~);
Using a concrete example:
int **array = NULL;
// notice, in following line that the second parameter to calloc()
// is the size of a pointer
array = calloc( 100, sizeof(int*) );
// each entry in the array[]
// must be set to point to some (more) allocated memory
for( int i=0; i<100; i++ )
{
array[i] = calloc( 20, sizeof( int ) );
}
Of course, each call to calloc() must be followed by a check to assure the returned value is not NULL.
Related
I am writing a mex code and I am thinking that I am not using memory very efficiently. Here is what I do. I am allocating memory for variable called out like
out=mxMalloc(sizeof(double)*N);
plhs[0]=mxCreateDoubleMatrix(1,N,mxREAL);
set(plhs[0],out);
The problem is that I am not freeing memory that I allocate for variable out because if I do I will receive segmentation error since I will use it in Matlab. So can anyone suggest me a better technique to do what above commands are doing ? Is there anyway to free memory for out or to avoid defining matrix of length 1X N?
Thanks.
You don't need to allocate the array with mxMalloc. mxCreateDoubleMatrix already allocates the array. Once you have your pointer to this data (obtained using mxGetPr), you can then fill the array with the necessary values.
double *out;
// Allocate memory for the first output
plhs[0] = mxCreateDoubleMatrix(1,N,mxREAL);
// Get the pointer to the output data
out = mxGetPr(plhs[0]);
// Run your algorithm here to populate out with the data you need
If for some reason you do need to create out in some other way, you want to copy the contents of that separate array into the output prior to freeing the memory.
double *out;
double *realout;
// Allocate data to use internally
out = mxMalloc(sizeof(double) * N);
// Initialize the array that will be returned to MATLAB
plhs[0] = mxCreateDoubleMatrix(1, N, mxREAL);
realout = mxGetPr(plhs[0]);
// Now copy all values to the MATLAB output
for ( j = 0; j < N; j++ )
realout[j] = out[j];
// Now you can free up memory for out
mxFree(out)
I have a 1d buffer which i have to re-organize to be accessed as a 2d array. I have pasted my code below:
#include <stdlib.h>
#include <stdio.h>
void alloc(int ** buf, int r, int c)
{
int **temp=buf;
for(int i=0; i<r; i++)
buf[i]=(int *)temp+i*c;
}
void main()
{
int *buffer=(int *)malloc(sizeof(int)*100);
int **p = (int**) buffer;
alloc(p, 4, 4);
//for(int i=0;i<r;i++)
//for(int j=0;j<c;j++)
// printf("\n %p",&p[i][j]);
p[0][3]=10;
p[2][3]=10;
p[3][2]=10; //fails here
printf("\n %d", p[2][3]);
}
The code is crashing when i make the assignment.
I have ran the code for different test cases. I have observed that the code crashes when there is an assignment to p[0][x] followed by assignment to p[x][anything] with the code crashing at the second assignment. This crash is seen only when the first index of the first assignment is 0 and for no other indices with the crash happening at the second assignment having the first index equal to the second index of the first assignment.
For example, in the above code crash happens at p[3][2] after p[0][3] has been executed. If i change the first assignment to p[0][2] then crash would happen at p[2][3]( or p[2][anything] for that matter).
I have checked the memory pointed to by p, by uncommenting the double for loop, and it seems to be fine. I was suspecting writing at illegal memory locations but that has been ruled out by the above observation.
The problem is that your 2D array is actually an array of pointers to arrays. That means you need to have space for the pointers. At the moment you have your pointers in positions 0-3 in the array, but p[0] is also pointing to position 0. When you write to 'p[0,3]' you are overwriting p[3].
One (tempting) way to fix it is to allow the pointers room at the start of the array. So you could change your alloc method to allow for some space at the front. Something like:
buf[i] = (int *)(temp+r) + i*c;
Note the +r adding to the temp. It needs to be added to temp before it is cast as you can't assume int and int * are the same type.
I would not recommend this method as you still have to remember to allocate extra space in your original malloc to account for the array of pointers. It also means you aren't just converting a 1D array to a 2D array.
Another option would be to allocate your array as an array of pointers to individually allocated arrays. This is the normal way to allocate 2D arrays. However this will not result in a contiguous array of data as you have in your 1D array.
Half way between these two options, you could allocate an extra array of pointers to hold the pointers you need, and then point them to the data. Change your alloc to something like:
int **alloc(int * buf, int r, int c)
{
int **temp = (int **)malloc(sizeof (int *)* r);
for (int i = 0; i<r; i++)
temp[i] = buf + i*c;
return temp;
}
then you call it like:
int **p = alloc(buffer, 4, 4);
you also need to free up the extra buffer.
This way your data and the pointers you need to access it are kept separate and you can keep your original 1D data contiguous.
Note that you don't need to cast the result of malloc in c, in fact some say that you shouldn't.
Also note that this method removes all of the requirement for casting pointers, anything that removes the need for a cast is a good thing.
I think that your fundamental problem is a misconception about 2D arrays in C (Your code is C, not C++).
A 2D array is a consecutive memory space , and the size of the inner array must be known in advance. So you basically cannot convert a 1D array into a 2D array unless the size of the inner array is known at compile time. If it is known, you can do something like
int *buffer=(int *)malloc(sizeof(int)*100);
typedef int FourInts[4];
FourInts *p = (FourInts *)buffer;
And you don't need an alloc function, the data is already aligned correctly.
If you don't know the size of the inner array in advance, you can define and allocate an array of arrays, pointing into the 1D buffer. Code for that:
int ** alloc(int * buf, int r, int c)
{
int **array2d = (int **) malloc(r*sizeof(int *));
for(int i=0; i<r; i++)
array2d[i] = buf+i*c;
return array2d;
}
void _tmain()
{
int *buffer=(int *)malloc(sizeof(int)*100);
int **p = alloc(buffer,4,4);
p[0][3]=10;
p[2][3]=10;
p[3][2]=10; //fails here
printf("\n %d", p[2][3]);
free(buffer);
free(p);
}
But it would have been easier to simply build an array of arrays without using the buffer. If you could use C++ instead of C, then everything could be easier.
If you already have a 1D block of data, the way to make it accessible as a 2D array is to create an array of pointers - one for each row. You point the first one to the start of the block, the next one is offset by the number of columns, etc.
int **b;
b = malloc(numrows*sizeof(int*));
b[0]=temp; // assuming temp is 1D block
for(int ii=1; ii<numrows;ii++)
b[ii]=b[0]+ii*numcols;
Now you can access b[i][j] and it will point to your original data. As long as number of rows and columns are known at run time this allows you to pass variable length 2D arrays around. Remember that you have to free the vector of pointers as well as the main data block when you are done or you will get a memory leak.
You will find examples of this if you google nrutil.c - this is derived from the trick Numerical Recipes in C uses.
This function prototype should be:
void alloc(int *buf[][], int r, int c) //buf[][] <=> **buf, but clearer in this case
{
//*(buf[i]) =
...
}
If you want to work on the same array you have to pass a pointer to this 2D array (*[][]).
The way you do it now is just working on a copy, so when you return it's not modified.
You should also initialize your array correctly :
p = malloc(sizeof(int *[]) * nb of row);
for each row
p[row] = malloc(sizeof(int []) * nb of col);
I'm working on a linking program, consisting of two files. The function createArray() creates an array of some length, which stores random numbers between 0 and 3. It's part of the second file, which gets linked with the first file to create a big program when it's compiled. I have all the declarations from the first file, including the extensions. Anyway, I compile and run the program, but I get a Segmentation Fault error, which I'm assuming it comes down to the line that actually puts the random number into the array.
int length;
int* intArray;
int maxRandVal;
void createArray(){
length = 16;
maxRandVal = 3;
intArray[length];
int i = 0;
for (i; i < length; i++){
int r = rand() % (maxRandVal+1);
intArray[i] = r;
}
}
I believe my error is that I'm trying to place an integer into a pointer array - something that I still don't understand how it works. How could I insert my random number into a pointer array?
Allocate memory for it first using malloc.
intArray = malloc(sizeof(int)*length);
The way you have done does not work. intArray[length]
Dont forget to free that memory once you are done with it .
Where is the intArray pointing to? Allocate memory using malloc for length 16.
intArray = malloc(sizeof(int)*length);
And what are you trying to achive by this:?
intArray[length];
I apologize if this is a waste of time and/or not what should be on this site, but I'm kind of out of ideas... I'm still a novice at programming, can't get a hold of my teacher for guidance, so... TO THE INTERNET!
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void months( FILE* monthfp, char** monthGroup );
int main (void){
FILE *monthfp; /*to be used for reading in months from months.txt*/
char** monthGroup;
int i;
if (( monthfp = fopen ( "months.txt", "r" )) == NULL ){
printf( "unable to open months.txt. \n" );
exit ( 1 );
}
months( monthfp, monthGroup );
/*test so far*/
for ( i = 0; i < 12; i++ ){
printf( "%s", monthGroup[i] );
}
fclose( monthfp );
}
void months ( FILE* monthfp, char** monthGroup ){
/*****************************************
name: months
input: input file, data array
returns: No return. Modifies array.
*/
char buffer[50];
int count = 0;
while ( fgets( buffer, sizeof(buffer), monthfp ) != NULL ){
count++;
monthGroup = malloc( count * sizeof ( char* ));
monthGroup[count] = malloc( sizeof( buffer ) * sizeof( char ));
strcpy(monthGroup[ count - 1 ], buffer );
}
}
I'm compiling in C89, everything seems to work, except for a segmentation fault. Any guidance would be very much appreciated.
edit
Thanks to everyone who took the time to provide a little bit of insight into something I've been having trouble wrapping my head around. I feel like a little kid in a village of elders in a foreign land. Much appreciation for the courtesy and guidance.
I'm afraid you don't realize how far you are from getting it right. Sit tight, this is going to be long. Welcome to C.
char** monthGroup
All this really means is "a pointer-to-pointer-to-char". However, C has many reasons why you would want to point to something. In your case, the "inner" pointing is so that you can actually point at a sequence of chars in memory (which you colloquially treat as a "string", which C properly does not have), and the "outer" pointing is so that you can point at a sequence of those char*s, and treat that sequence as an "array" (even though it isn't; you're going to dynamically allocate it).
Here's the problem: When you pass in this char** that came from main, it doesn't actually point at anything. "That's fine", you say; "the function is going to make it point at some memory that I'll allocate with malloc()".
Nope.
C passes everything by value. The char** that months receives is a copy of the char** in main's chunk of local variables. You overwrite the pointer (with the result of the malloc call), write some pointers into that pointed-at memory (more malloc results), copy some data into those chunks of pointed-at memory... and then, at the end of the function, the parameter monthGroup (which is a local variable in months) no longer exists, and you've lost all that data, and the variable monthGroup in main is still unchanged at pointing at nothing. When you try to use it as if it points at something, boom you're dead.
So how do we get around this? With another level of pointing, of course, C properly does not have "pass by reference", so we must fake it. We accept a char***, and pass it &monthGroup. This is still a copied value, but it points directly into the local variable storage for that invocation of main (on the stack). That lets us write a value that will be visible in main. We assign the first malloc result to *monthGroup, and write pointers into that storage (*monthGroup[count]), etc.
Except we don't really want to do that, because it's incredibly ugly and confusing and hard to get right. Let's instead do what should be an incredibly obvious thing that you're meant to do and that basic instruction doesn't emphasize nearly enough: use the return value of the function to return the result of the calculation - that's why it's called the return value.
That is, we set up a char** in months (not accepting any kind of parameter for it), return it, and use it to initialize the value in main.
Are we done? No.
You still have some logical errors:
You re-allocate the "outer" layer within your while-loop. That's clearly not what you want; you're allocating several "strings", but only one "array", so that allocation goes outside the loop. Otherwise, you throw away (without properly deallocating them!) the old arrays each time.
Actually, you do want to do something like this, but only because you don't know in advance how many elements you need. The problem is that the new allocation is just that - a new allocation - not containing the previously-set-up pointers.
Fortunately, C has a solution for this: realloc. This will allocate the new memory, copy the old contents across (the pointers to your allocated "strings"), and deallocate the old chunk. Hooray! Better yet, realloc will behave like malloc if we give it a NULL pointer for the "old memory". That lets us avoid special-casing our loop.
You're using the value count incorrectly. The first time through the loop, you'll increment count to 1, allocate some space for monthGroup[1] to point at, and then attempt to write into the space pointed at by monthGroup[0], which was never set up. You want to write into the same space for a "string" that you just allocated. (BTW, sizeof(char) is useless: it is always 1. Even if your system uses more than 8 bits to represent a char! The char is the fundamental unit of storage on your system.)
Except not, because there's a simpler way: use strdup to get a pointer to an allocated copy of your buffer.
char** months(FILE* monthfp) {
char buffer[50];
int count = 0;
char** monthGroup = NULL;
while (fgets(buffer, sizeof(buffer), monthfp) != NULL) {
// (re-)allocate the storage:
monthGroup = realloc(monthGroup, count * sizeof(char*));
// ask for a duplicate of the buffer contents, and put a pointer to the
// duplicate sequence into the last element of the storage:
monthGroup[count - 1] = strdup(buffer);
}
return monthGroup;
}
Adjusting main to match is left as a (hopefully trivial) exercise. Please also read the documentation for realloc and strdup.
Are we done? No.
You should still be checking for NULL returns from realloc and strdup (since they both attempt to allocate memory, and thus may fail in that way in C), and you still need code to free the allocated memory.
And, as others pointed out, you shouldn't be assuming there will be 12 months. If you could assume that, you wouldn't be dynamically allocating monthGroup in the first place; you'd just use an array. So you need to communicate the size of the result "array" somehow (adding an explicit NULL pointer to the end is one way; another is to do the horribly ugly thing, pass in a char***, and use the return value to count the size).
C has pass-by-value semantics for function calls. This is a fancy way of saying that
int main() {
int a = 5;
addOneTo(a);
printf("%d\n", a);
return 0;
}
will print 5 no matter what addOneTo() does to its parameter.
In your code, your months() function sets its local variable monthGroup to the value returned by the first malloc(), then throws away that value when it returns.
You have a few choices here on how to fix this problem. You could malloc into monthGroup outside the months() function then pass it in. You could return the monthGroup value. Or you could pass a pointer to monthGroup for pass-by-reference semantics (char***).
In any case, I would encourage you to learn how to use a debugger (e.g. gdb) so you can see why it segfaults next time!
Your problem lies in the months function, specifically your understanding of how memory works.
Looking at your code:
monthGroup = malloc( count * sizeof ( char* ));
This line allocates a chunk of memory which is equivalent to an array of char * of size count.
monthGroup[count] = malloc( sizeof( buffer ) * sizeof( char ));
Here, a buffer is allocated of size sizeof (buffer) (the sizeof (char) is unneccesary). This is one problem here: you are assigning it to monthGroup[count]. Arrays in C are zero-base, which means that the array:
int array [3];
has elements:
array [0], array [1] and array [2]
array [3] is outside the memory of the array. So monthGroup[count] is also outside the memory of the array. You want monthGroup[count-1] instead. This will write to the last element in the array.
The second problem is that every time you do the first allocation, you lose the previously allocated data (this is know as a memory leak) and the data it contained.
To fix this, there are two approaches.
When allocating the array, copy the contents of the old array to the new array:
oldarray = monthGroup;
monthGroup = malloc (count * sizeof (char *))
memcpy (monthGroup, oldarray, count-1 * sizeof (char *));
free (oldarray);
monthGroup [count-1] = ....
or use realloc.
Use a linked list. A lot more complex this one but has the advantage of not requiring the arrays to be copied every time a new item is read.
Also, the monthGroup parameter doesn't get passed back to the caller. Either change the function to:
char **months (FILE *fp)
or:
void months (FILE *fp, char ***ugly_pointer)
Finally, the caller currently assumes that there are 12 entries and attempts to print each one out. What happens if there are fewer than 12, or more than 12? One way to cope is to use a special pointer to terminate the monthsGroup array, a NULL would do nicely. Just allocate one extra element to the array and set the last one to NULL.
To me the most obvious of your problems is that you pass char** monthGroup as a parameter by value, then malloc it inside the function months, and afterwards try to use it in the caller function. However, since you passed it by value, you only stored the malloced address in a local copy of monthGroup, which does not change the value of the original variable in main.
As a quick fix, you need to pass a pointer to monthGroup, rather than (a copy of) its current value:
int main (void){
...
char** monthGroup;
...
months( monthfp, &monthGroup );
...
}
void months ( FILE* monthfp, char*** monthGroup ){
...
*monthGroup = malloc( count * sizeof ( char* ));
...
}
This is ugly (IMHO there should be no real reason to use char*** in real code) but at least a step in the right direction.
Then, as others rightly mentioned, you should also rethink your approach of reallocating monthGroup in a loop and forgetting about the previous allocations, leaving memory leaks and dangling pointers behind. What happens in the loop in your current code is
// read the first bunch of text from the file
count++;
// count is now 1
monthGroup = malloc( count * sizeof ( char* ));
// you allocated an array of size 1
monthGroup[count] = malloc( sizeof( buffer ) * sizeof( char ));
// you try to write to the element at index 1 - another segfault!
// should be monthGroup[count - 1] as below
strcpy(monthGroup[ count - 1 ], buffer );
Even with the fix suggested above, after 10 iterations, you are bound to have an array of 10 elements, the first 9 of which are dangling pointers and only the 10th pointing to a valid address.
The completed code would be this:
int main (void)
{
FILE *monthfp; /*to be used for reading in months from months.txt*/
char **monthGroup = NULL;
char **iter;
if ((monthfp = fopen("c:\\months.txt", "r")) == NULL){
printf("unable to open months.txt. \n");
exit(1);
}
months(monthfp, &monthGroup);
iter = monthGroup;
/* We know that the last element is NULL, and that element will stop the while */
while (*iter) {
printf("%s", *iter);
free(*iter);
iter++;
}
/* Remember that you were modifying iter, so you have to discard it */
free(monthGroup);
fclose(monthfp);
}
void months(FILE *monthfp, char ***monthGroup)
{
/*****************************************
name: months
input: input file, data array
returns: No return. Modifies array.
*/
char buffer[50];
int count = 0;
while (fgets(buffer, sizeof(buffer), monthfp) != NULL){
count++;
/* We realloc the buffer */
*monthGroup = (char**)realloc(*monthGroup, count * sizeof(char**));
/* Here I'm allocating an exact buffer by counting the length of the line using strlen */
(*monthGroup)[count - 1] = (char*)malloc((strlen(buffer) + 1) * sizeof( char ));
strcpy((*monthGroup)[count - 1], buffer);
}
/* We add a terminating NULL element here. Other possibility would be returning count. */
count++;
*monthGroup = (char**)realloc(*monthGroup, count * sizeof(char**));
(*monthGroup)[count - 1] = NULL;
}
As said by others a char*** is ugly.
The principal error that I see immediately, is that your allocation for monthGroup will never make it back into your main.
For an assignment at school, we have to use structs to make matrices that can store a infinite amount of points for an infinite amount of matrices. (theoretical infinite)
For the assignment I decided to use calloc and realloc. How the sizes for the matrix go is: It doubles in size every time its limit is hit for its points (so it starts at 1, then goes to 2, then 4 and so on). It also doubles in size every time a matrix is added as well.
This is where my issue lies. After the initial matrix is added, and it goes to add the second matrix name and points, it gives me the following:
B???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
B is the portion of it that I want (as I use strcmp later on), but the ? marks are not supposed to be there. (obviously)
I am not sure why it is exactly doing this. Since the code is modular it isn't very easy to get portions of it to show exactly how it is going about this.
Note: I can access the points of the matrix via its method of: MyMatrix[1].points[0].x_cord; (this is just an example)
Sample code that produces problem:
STRUCTS:
struct matrice {
char M_name[256];
int num_points[128];
int set_points[128];
int hasValues[1];
struct matrice_points * points;
} * MyMatrix;
struct matrice_points {
int set[1];
double cord_x;
double cord_y;
};
Setup Matrix Function:
void setupMatrix(){
MyMatrix = calloc(1, sizeof(*MyMatrix));
numMatrix = 1;
}
Grow Matrix Function:
void growMatrix(){
MyMatrix = realloc(MyMatrix, numMatrix * 2 * sizeof(*MyMatrix));
numMatrix = numMatrix * 2;
}
Add Matrix Function which outputs this problem after growing the matrix once.
void addMatrix(char Name, int Location){
int exists = 0;
int existsLocation = 0;
for (int i = 0; i < numMatrix; i++){
if (strcmp(MyMatrix[i].M_name, &Name) == 0){
exists = 1;
existsLocation = i;
}
}
*MyMatrix[Location].M_name = Name;
printf("Stored Name: %s\n", MyMatrix[Location].M_name);
*MyMatrix[Location].num_points = 1;
*MyMatrix[Location].set_points = 0;
*MyMatrix[Location].hasValues = 1;
MyMatrix[Location].points = calloc(1, sizeof(*MyMatrix[Location].points));
}
void addMatrix(char Name, int Location)
char Name represents a single char, i.e. a integer-type quantity. char is just a number, it's not a string at all.
When you do this:
strcmp(..., &Name)
you're assuming that the location where that one character is stored represents a valid C string. This is wrong, there is no reason why this should be the case. If you want to pass a C string to this function, you will need to declare it like this:
void addMatrix(char *Name, int Location)
Then you need to copy that C string into the appropriate place in your matrix structure. It should look like:
strncpy(... .M_name, Name, max_number_of_chars_you_can_store_in_M_Name);
Also these field definitions are strange in your struct:
int num_points[128];
int set_points[128];
int hasValues[1];
This means that your struct will contain an array of 128 ints called num_points, another array of 128 ints calls set_points, and an array of one int (strange) called hasValues. If you only need to store the count of total points and set points, and a flag indicating whether values are stored, the definition should be:
int num_points;
int set_points;
int hasValues;
and correct the assignments in your addMatrix function.
If you do need those arrays, then your assignments as they are are wrong also.
Please turn on all warnings in your compiler.
Try adding '\0' to the end of your data.
*MyMatrix[Location].M_name = Name;
You're copying a single character here, not a string. If you want a string, Name should be defined as char *, and you should be using strcpy.