I have some code, but for some reason the location of a variable changes in the middle of my code.
In my main I read one integer from stdin, then malloc an array of structs.
int main(){
int numcities;
scanf("%d", &numcities);
City **cities = malloc(numcities*sizeof(City)*2); //*2 is just to be sure, gonna remove that later.
for(int n = 0;n<numcities;n++){
int nularr[numcities];
for(int n2 = 0;n2<numcities;n2++){
nularr[n2] = 0;
}
City c = {
.value = 1,
.options = nularr,
};
cities[n] = &c;
};
readRoads(cities, numcities);
}
readRoads is shown below. before calling readRoads I can access numcities (gdb and inside the code), but after it sigsegvs when trying to use it, and in gdb complains about not being able to read memory at 0xffffffcd.
If I take a pointer to numcities and dereference it later, everything is intact. but getting the pointer after calling readRoads gives me 0xffffffcd (consistently) which is unreadable.
I already receive twice as much memory from malloc as necessary,
void readRoads(City **cities, int N){
for(int n = 0;n<N;n++){
int buf;
int res[N];
int roads = 0;
City *options[N];
scanf("%d", &buf);
for(int r = 0;r<N;r++){
res[r]= buf << r;
if(res[r]){
options[roads] = cities[r];
roads++;
}
}
cities[n]->id = n;
cities[n]->name = n +'A';
cities[n]->optionsCount = 1;
for(int i = 0; i < roads; i++){
cities[n]->options[i] = options[i]->id;
}
}
}
When you assign to the cities array:
for(int n = 0;n<numcities;n++){
int nularr[numcities];
for(int n2 = 0;n2<numcities;n2++){
nularr[n2] = 0;
}
City c = {
.value = 1,
.options = nularr,
};
cities[n] = &c;
};
You're assigning the address of a local variable. This variable goes out of scope at the end of the for loop, so you end up pointing to invalid memory. Dereferencing this invalid pointer invokes undefined behaivor. The same thing happens when you assign nularr to one of these instances
Rather than create an array of pointers to City, just create an array of City. Also, you'll need to dynamically allocate nularr.
City *cities = malloc(numcities*sizeof(City));
for(int n = 0;n<numcities;n++){
int *nularr = calloc(numcities, sizeof(int);
cities[n].value = 1;
cities[n].options = nularr;
};
Also change readRoads accordingly:
void readRoads(City *cities, int N){
...
And be sure to check the return value of malloc / calloc for errors.
City c = {
.value = 1,
.options = nularr,
};
cities[n] = &c;
}
At this }, c goes out of scope and stops existing (it's a local variable in that block).
The pointer you just saved (cities[n]) has become indeterminate.
Basically, cities is now an array of invalid pointers.
(Also, it should be initialized as
City **cities = malloc(numcities * sizeof (City *));
Specifically, sizeof (City *), not sizeof (City).)
Related
I use nested data structure for fibonacci, but I have a segmentation fault 11.
void fib(int **fib_array, int n){
fib_array = malloc(n * sizeof(int*));
for(int i = 0; i < n; i++){
fib_array[i] = malloc(sizeof(int));
}
for(int i = 0; i < n; i++){
if (i <= 1){
fib_array[i][0] = i;
}
else{
fib_array[i][0] = fib_array[i - 2][0] + fib_array[i - 1][0];
}
}
}
int main(int argc, char **argv) {
/* do not change this main function */
int count = strtol(argv[1], NULL, 10);
int *fib_sequence;
fib(&fib_sequence, count);
for (int i = 0; i < count; i++) {
printf("%d ", fib_sequence[i]);
}
free(fib_sequence);
return 0;
}
you are being too complicated. You just need a single malloc
*fib_array = malloc(n * sizeof(int));
and remove you second indexings [0] from everywhere
The consfusion comes from **int. This looks like a multi dim array. Its not - its declared ** so that you can set the value in the caller. A simpler exampe will help
void Make42(int* v)
{
*v = 42;
}
int main()
{
int myv = 0;
Make42(&myv);
// now myv == 42
}
The * in the arg list is so that Make42 can 'reach out' and modify what was passed to it (myv in this case)
In your code the ** on fib array is there for the same purpose. you could have done (In know you werent allowed to by the test definition )
int *fib(int n){
int *fib_array = malloc(n * sizeof(int));
......
return fib_array;
}
and in main
fib_sequence = fib(count);
this makes it much clearer that you are really manipulating a simple array
pm100 is right, but a little short for answering to a beginner...
At first, you have passed a pointer to a pointer. If you want the original pointer to contain a value, you need to dereference the pointer to pointer:
*fib_array = ...
By assigning to the pointer only (as you did in your code), you do not modify the orignial pointer (fib_sequence in main) at all. And as you have not initialised it, it might point to anywhere, thus the segmentation fault when you try to print the values of it.
Then why an array of pointers to individually stored values? You can use a contiguous array of ints, which you get by
*fib_array = malloc(n * sizeof(int));
OK, further usage won't be too nice ((*fib_array)[i] = ...), so I recommend a temporary variable instead:
int* fa = malloc(n * sizeof(int));
// now fill in the values comfortably:
fa[i] = ...;
// finally, assign the pointer to the target:
*fib_array = fa;
Side note: always check the result of malloc, it could be NULL:
fa = ...
if(fa)
// assign values
else
// appropriate error handling
In your concrete case, you could omit the else branch in your function and check your pointer outside within main function.
By the way, a simple return value would have made your live easier, too:
int* fib(int n)
{
int* fib_array = malloc(n * sizeof(int*));
// ...
return fib_array;
}
Notice: no need for pointer to pointer... Usage:
int* fib_sequence = fib(count);
int staticArrayA[10];
int staticArrayB[10];
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = (int *)malloc(sizeof(int) * 10);
From what I understand, the value of staticArrayA is a pointer to the 1st element in the array, however the pointer that represents this base address behaves like a const pointer and cannot be changed, in which case it makes sense that you cannot set:
staticArrayA = staticArrayB;
But what about dynamic arrays? if they are both just pointers to a contiguous block of bytes in memory, then why can't you set them equal to eachother?
dynamicArrayA = dynamicArrayB;
It seems like the address that dynamicArrayA points to would now be the same address that dynamicArrayB points to. Please give me some insight. Perhaps I am wrong, but here is what I was trying to do:
/* remove any element that is 0 from array. n is size of array */
void compressArray(int *array, int n) {
int size = n;
int index = 0;
int *nuArray = (int *)malloc(sizeof(int) * n);
assert(nuArray != NULL);
for (int i = 0; i < n; i++) {
if (array[i] != 0) {
nuArray[index] = array[i];
index++;
size--;
}
}
nuArray = realloc(nuArray, sizeof(int) * size);
assert(nuArray != NULL);
array = realloc(array, sizeof(int) * size);
assert(array != NULL);
array = nuArray; //This doesn't seem to work
free(nuArray);
}
int main(int argc, const char * argv[]) {
int *array = (int *)malloc(sizeof(int) * 10);
assert(array != NULL);
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
array[i] = 0;
} else {
array[i] = i;
}
}
compressArray(array, 10);
return 0;
}
I am sure that there are much simpler and more elegant ways to write the function, and i know that I can copy all the elements of nuArray into array and then use realloc() to reduce the size, however, I am just hoping someone can give some insight into the nature of dynamic arrays and explain some of this behavior and tell me why the assignment does not work, or if there are cases in which it does. Also, i could have the function return an int * and set array = to this function call and that works, however why can't i do it inside the function? Thanks for your time and for any help.
if they are both just pointers to a contiguous block of bytes in memory, then why can't you set them equal to each other?
Of course you can. You just have to know the ramifications.
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = dynamicArrayA;
Now dynamicArrayB and dynamicArrayA point to the same memory. You change the value of what one points to, the change will be visible through other pointer too.
dynamicArrayB[0] = 10; // dynamicArrayA[0] is 10.
dynamicArrayA[5] = 15; // dynamicArrayB[5] is 15.
If that's your objective, you can do that without any problem.
Update, in response to OP's comment
The line
array = nuArray; //This doesn't seem to work
changes the value of array locally in compressArray. That does not change the value of array in main.
You'll have to come up with a different method to return nuArray back to main.
One solution to the problem would be to change the return type of compressArray from void to char* and return nuArray from the function.
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = (int *)malloc(sizeof(int) * 10);
After this if you do this ( which ofcourse is possible ) -
dynamicArrayA = dynamicArrayB; //you want this then don't allocate memory to dynamicArrayA
Now , dynamicArrayA won't point to memory allocate by malloc to it previously , so you won't be able to free that memory block . Thus , can lead to memory leak.
You can use memcpy for this task -
/* allocate memory to both dynamicArrayA and to dynamicArrayB */
for(int i=0;i<10;i++){
dynamicArrayA[i]=i+1; // store value in dynamicArrayA
}
memcpy(dynamicArrayB,dynamicArrayA,sizeof(int)*10); //copy it to dynamicArrayB
for(int i=0;i<10;i++)
printf("%d",dynamicArrayB[i]); // print values
free(dynamicArrayA);
free(dynamicArrayB);
Let's take a look at what's actually happening at the end of compressArray:
array = nuArray;
After this statement, array now points to the same memory that nuArray points to. The memory that array previously pointed to is now accessible inside of compressArray, however array in main still points to the original memory block. That's because the address of this block is what was passed to compressArray, not the address of the array variable.
free(nuArray);
This frees the memory pointed to by nuArray. But since array contains the same value as nuArray, i.e. the address of the memory block pointed to by nuArray, now array points to a freed block of memory, and accessing it is undefined behavior.
When the function returns, the value of array in main is unchanged. That's because the value of array was passed in.
For this to work as expected, compressArray needs to take the address of a pointer (an int **) and change what that points to:
void compressArray(int **array, int n) { // "array" is a pointer to an array
int size = n;
int index = 0;
int *nuArray = (int *)malloc(sizeof(int) * n);
assert(nuArray != NULL);
for (int i = 0; i < n; i++) {
if ((*array)[i] != 0) { // note how we're now accessing the array
nuArray[index] = (*array)[i]; // same here
index++;
size--;
}
}
nuArray = realloc(nuArray, sizeof(int) * size);
assert(nuArray != NULL);
free(*array); // We don't need the memory array pointed to anymore, so free it
*array = nuArray; // This changes "array" in main. Also, don't free nuArray,
// otherwise *array will also point to freed memory
}
Then you call it like this:
compressArray(&array, 10);
// print the new contents of array
free(array); // We're done with it now, so free it
I'm new to C and still learning about pointers. I was just testing my understanding of pointers by trying to simulate appending to an array when I got an Access Violation Read Loaction error when using printf. This is the code:
#include <stdio.h>
#include <stdlib.h>
int arraySize(int *arrayToSize);
void changeAll(int ***a1PtrPtrPtr, int nToAdd){
int *bPtr = (int *)malloc((arraySize(**a1PtrPtrPtr) + 1) * sizeof(int));
int i = 0;
while (*(**a1PtrPtrPtr + i) != -1){
bPtr[i] = *(**a1PtrPtrPtr + i);
i++;
}
bPtr[i] = nToAdd; i++;
bPtr[i] = -1;
*a1PtrPtrPtr = &bPtr;
}
int main(void){
int a[4] = { 1, 2, 3, -1 };
int *aPtr = a;
int **aPtrPtr = &aPtr;
int ***aPtrPtrPtr = &aPtrPtr;
int n = 4;
changeAll(aPtrPtrPtr, n);
int counter = 0;
while (counter < 5){
int temp = *(*aPtrPtr + counter);
printf("%d is %d", counter, temp );
counter++;
}
return 0;
}
int arraySize(int *arrayToSize){
int sizeTemp = 0;
int i = 0;
while (arrayToSize[i] != -1){
sizeTemp++;
i++;
}
sizeTemp++;
return sizeTemp;
}
I get the error the second time I print in the while loop in main() when counter = 1. What I don't understand is that if I comment out that printf statement and look at the value of temp value in my IDE (MVSE 2013) it is exactly as I wanted and expected i.e. temp will be 1 then 2,3,4,-1.
What is going on please and thanks in advance for any help.
Firstly, in case you're wondering how this appeared to sometimes work, you really should read this stellar answer to another somewhat related question.
In short, you're saving an address to an automatic variable from inside a function, then treating said-address like it is still valid after the function returns. That the automatic variable is a pointer referring to dynamic data is irrelevant. The variable itself is no longer valid once the function expires, and thus dereferencing its use-to-be-address invokes undefined behavior:
void changeAll(int ***a1PtrPtrPtr, int nToAdd)
{
// NOTE: local variable here
int *bPtr = (int *)malloc((arraySize(**a1PtrPtrPtr) + 1) * sizeof(int));
int i = 0;
while (*(**a1PtrPtrPtr + i) != -1){
bPtr[i] = *(**a1PtrPtrPtr + i);
i++;
}
bPtr[i] = nToAdd; i++;
bPtr[i] = -1;
// NOTE: saving address of local variable here
*a1PtrPtrPtr = &bPtr;
}
With how this is setup, the quickest fix is simply this:
**a1PtrPtrPtr = bPtr;
instead of what you have. This will save the dynamic allocation result to the correct location (which is ultimately the address held in aPtr back in main()). It looks hideous (and frankly, it is), but it will work.
Best of luck.
I tried different methods but eventually got errors. Please give a solution and a brief explanation of the concept.
uint8_t **subBytes()
{
int i,j;
uint8_t r,c;
uint8_t t[4][4];
for(i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
r = pt[p1][j] & 0xf0;
r = r >> 4;
c = pt[p1][j] & 0x0f;
t[i][j] = (uint8_t *) malloc(sizeof(uint8_t));
t[i][j] = sBox[r][c];
}
p1++;
}
return t;
}
int main()
{
uint8_t **temp;
temp = subBytes();
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("%x ", temp[i][j]);
}
printf("\n");
}
}
This is my original code. Here, I used malloc, but then too it is not working.
the memory space alloced for your matrix is a LOCAL VARIABLE.
The scope of a LOCAL VARIABLE is only within that function.
When you returned it is discarded.
In your code it is uint8_t t[4][4].
t is discarded right after return t.
So you return nothing and may cause undefined behavior.
You should use malloc to alloc memory for your matrix not just declare it locally.
in code
uint8_t **t.
t = malloc(sizeof(uint8_t) * 16 ) //size of a 4x4 matrix
then use t as a two dimension array and return t.like
t[0][0] = 1;
don't forgot to free it after use it out side of the function.
free(t);
m is LOCAL VARIABLES. When add returns, m is DESTROYED!
You SHOULD NOT return the pointer or reference of local variables. Look the following code:
int foo() { return 1; }
int *bar() { int i = 1; return &i; }
When I call foo(), it returns 1.
When I call bar(), it try to return the local variables, i's address. But when bar() returns, the i variable is DESTROYED! So the return pointer become trash pointer. (Sorry, I don't know how to say that term in English;)
You should use like that:
void bar(int *ret) { *ret = 1; }
int i;
bar(&i); /* now i is 1 */
or
int *bar()
{
int *p = (int *)malloc(sizeof(int));
*p = 1;
return p;
}
int *pi = bar();
/* now *pi is 1 */
...
free(pi); /* You MUST free pi. If not, memory lack is coming~ */
(I recommend first one. the second one require free and it can be mistaken.)
When a variable is declared (statically allocated) within a function, it is placed on what is called the stack, which is only local to that function. When the program leaves that function's scope, the variable is no longer guaranteed to be preserved, and so the pointer you return to it is essentially useless.
You have three options to fix your error:
Don't do it
Simply declare the array in the same function as you use it, don't bother with trying to return a pointer from another function.
Pass a pointer to a variable local to main
A pointer to a variable local to main will be valid until main returns, so you could do this:
void subBytes(uint8_t t[4][4]){
//perform initialization of matrix on passed variable
}
int main(){
uint8_t temp[4][4];
subBytes(&temp);
//...
}
Dynamic Allocation
This will probably give you more errors than it will solve in this case, but if you are heartset on returning a pointer to a matrix, you could malloc() the memory for the array and then return it, but you would have to free() it afterwards.
In C, there are several ways to dynamically allocate a 2D array. The first is to create it as a single array, and operate on the indices to treat it as 2D.
//...
int *arr = (int *)malloc(rows*cols*sizeof(int));
for (int i = 0; i<rows; i++){
for (int j = 0; j<height; j++){
arr[i*height + j] = i*j; //whatever
}
}
return arr; // type is int *
//...
Note that in this method, you cannot use array[i][j] syntax, because the compiler doesn't know the width and height.
The second way is to treat it as an array of arrays, so store an array of pointers to other arrays.
//...
int **arr = (int **)malloc(rows*sizeof(int *));
for (int i = 0; i<rows; i++){
arr[i] = (int *)malloc(cols*sizeof(int));
}
arr[i][j] = 86; //whatever
return arr; //type is int **
//...
For further information, see: Pointer to Local Variable
I have an array of pointer to struct, and for any reasons when I print this array, there is a spare element at the end of it, and thus causes the code to print a NULL byte at the end.
Is there anyway I can delete the last chunk of memory?
For example:
typedef struct
{
char *name;
} B;
typedef struct
{
B *var;
} A;
int main() {
int num = 5; //for example
A *foo = malloc(sizeof(A));
B *bar = malloc(num * sizeof(B));
for (int i = 0; i < num; i++) {
bar[i] = *create_b(&bar[i]); // some function that works.
}
foo->var = bar;
while (foo->var != NULL) {
printf("This is %s\n",foo->var->name);
foo->var++;
}
}
Everything is printed out just fine, but there's an unwanted printing at the end of the loop. Something like:
This is A
This is B
This is C
This is D
This is F
This is
Apparently the array only has 5 elements, the last one prints nothing.
Your printing loop is:
foo->var = bar;
while (foo->var != NULL) {
printf("This is %s\n",foo->var->name);
foo->var++;
}
But foo->var will never equal NULL, since you're just incrementing a pointer, so you will eventually read past the end of the bar array and your application will probably crash.
If you replace the while loop with for (int i = 0; i < num; i++), it will print the correct number of elements.
You can't do foo->var++, because there is no place in the array that is set to NULL. Also, using that ++ changes foo->var so after the loop foo->var no longer points at the start of the array, and you can not access the array again.
You need to allocate memory for some end-of-array marker, just like strings has the character \0 to mark the end of the string.
Try the following:
int main() {
int num = 5; //for example
A *foo = malloc(sizeof(A));
B *bar = malloc((num + 1) * sizeof(B)); // +1 for array terminator
for (int i = 0; i < num; i++) {
bar[i] = *create_b(&bar[i]); // some function that works.
}
bar[i].name = NULL; // Use this as a marker to mean end of array
foo->var = bar;
for (B *tmp = foo->var; tmp->name != NULL; tmp++) {
printf("This is %s\n",tmp->name);
}
}
Edit Had some errors in the code.
Your problem is probably in the function create_b, which you did not post.
Edit: no, that's probably wrong, sorry.
But surely this isn't what you want:
bar[i] = *create_b(&bar[i]);
You both pass in the address of bar[i] and set it equal to whatever the return value points to?