Reputation: 351
I'm writing a C program. I want to read data from test.txt
file. In my (.txt) file is a list of hexadecimal numbers 8-bit such as: 2A 8E 5A. Then I write these numbers to an array A
. I have an error when I using Release mode in Visual Studio. Please tell me what's wrong?
int main(int argc, char *argv[]) {
FILE *FileIn;
int i, temp;
int *A, nA = 0;
A = (int *)realloc(NULL, sizeof(int));
FileIn = fopen("test.txt", "r");
// Add frist value to array.
fscanf(FileIn, "%x", &temp);
A[0] = temp;
nA++;
for(i = 0; i < 16; ++i){
fscanf(FileIn, "%x", &temp);
addValue(A, &nA, temp);
}
for (i = 0; i < 16; ++i) {
printf("A[%d] = %x\n", i, A[i]);
}
free(A);
system("pause");
return 0;
}
void addValue(int *A, int *n, int Data)
{
A = (int *)realloc(A, (*n+1)*sizeof(int *));
A[*n] = Data;
(*n)++;
}
Upvotes: 1
Views: 624
Reputation: 8142
The problem is that with the addValue
, it calls realloc
but that value is only local to the function. You update the value of nA
by passing it by reference, so you could either do that with A
or have the function return the local version.
For example to do the second you change addValue
to return int *
and have it return the local value of A
int *addValue(int *A, int *n, int Data)
{
A = realloc(A, (*n+1)*sizeof(*A));
A[*n] = Data;
(*n)++;
return(A);
}
then when you call it you assign the return value to A
like this
A=addValue(A,&nA,temp);
then, A
will update each time you call that function.
It was also using the wrong datatype (int *
) in the sizeof
when it should have been int
so I've also corrected that. By using *A
, no matter what datatype A
is, it'll always allocate the right size of memory.
Upvotes: 2
Reputation: 15103
Here's what is really going on.
Let's take this example of some memory allocations packed together:
| some memory (10 bytes) | A (5 bytes) | unallocated (10 bytes) |
When you call realloc(A, 15)
in the above scenario the system is able to expand the allocated memory at the same location:
| some memory (10 bytes) | A (15 bytes) |
However, what happens in the following case?
| some memory (10 bytes) | A (5 bytes) | some memory (10 bytes) |
This time, realloc(A, 15)
can't simply expand the previously allocated region of memory since the latter 10 bytes it needs to expand A
are currently allocated.
Instead, it has to do the equivalent of malloc()
-ing a new memory region of 15 bytes and copying the original 5 bytes from A
's old memory region to the first 5 bytes of the new region.
In that case, realloc()
has not just expanded your memory allocation, but it has also moved the memory to a location where it can contiguously exist.
There are a few other reasons why realloc()
would move memory (not just size requirements) but a lot of those are implementation defined.
Due to the possibility of a memory move, realloc()
returns the address of the new pointer. As demonstrated above, sometimes it's the same pointer, and sometimes it's a new pointer.
When a move occurs, the old pointer is no longer valid as it is free()
'd by the system. If you try to access it, you'll receive an access violation/segmentation fault.
In your example, you're realloc()
-ing the memory in addValue()
but you're never updating the caller's pointer. When the caller goes to use the old pointer, if a move occurred in addValue()
, then the memory it tries to use will thus be invalid and the whole thing will crash and burn.
One way you could solve this is to pass a pointer to a pointer.
void addValue(int **A, int *n, int Data)
{
*A = realloc(*A, (*n+1)*sizeof(int *));
(*A)[*n] = Data;
(*n)++;
}
And call it appropriately:
addValue(&A, &nA, temp);
A final note: In C, you don't need to cast the result of malloc()
or realloc()
- unlike C++, void*
is implicitly cast-able to any other pointer type.
Upvotes: 3
Reputation: 4044
reallocated pointer stays in local copy of A in addValue
Variable A from main has only one int allocated when you go to print, loop goes on accessing till A[15] leading to undefined behaviour
Upvotes: 0