Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am trying to debug a text editor program where I create a 2D array that doubles its size every time there's a new input from a file. Valgrind returns this:
==1454== Process terminating with default action of signal 6 (SIGABRT)
==1454== at 0x48A518B: raise (raise.c:51)
==1454== by 0x4884858: abort (abort.c:79)
==1454== by 0x48EF3ED: __libc_message (libc_fatal.c:155)
==1454== by 0x49919B9: __fortify_fail (fortify_fail.c:26)
==1454== by 0x4991985: __stack_chk_fail (stack_chk_fail.c:24)
==1454== by 0x10980C: main (in /home/utente/Desktop/main)
here's my main where I call a fun to reallocate the array
int main() {
FILE *fp;
cmd istruction;
char **Array = {0};
fp=fopen("prova.txt", "rt");
int dim=30;
Array = Create2D(H);
istruction=GetOrder(fp);
while (dim<variable) {
Array = Reallocation2D(Array,dim);
dim=dim*2;
}
doing stuff...
}
}
free2D(Array, dim);
fclose(fp);
}
the create array and reallocation2D are
char ** Create2D(ssize_t Strings)
{
char **a = {0};
a = calloc(Strings, sizeof(char *));
return a;
}
char ** Reallocation2D(char ** a, size_t dim){
int i;
char **b = {0};
b = calloc(dim*2, sizeof(char *));
for(i=0;i<dim*2; i++)
{
b[i] = calloc(1024, 1);
}
for(i=0;i<dim;i++){
if(a[i]) strcpy(b[i],a[i]);
}
for(i=0;i<dim; i++)
{
if(a[i]) free(a[i]);
}
free(a);
return b;
}
Without the code, one can only try and analyse valgrind's output:
The problem seems to occur in the main() function where you have a stack overflow. Do you call a function that define a very large automatic array? Or do you define such an array in main() itself?
From the posted code, here are some problems:
the initial call to Create2D allocates space for a H pointers, but you initialize dim to 30. H is not defined, is it a #define for 30?
where does variable get set?
why do you reallocate the char arrays instead of copying them?
you allocate lines with a size of 1024 bytes. This may use much more code memory than the file on disk an would still not suffice if a line in the file os longer than that.
why not use realloc() in Reallocation2D and initialize the newly allocated part to NULL pointers?
you should test for allocation failure and report it.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Stack create(int c)
{
Stack S=(Stack)malloc(sizeof(struct stack));
S->size=c;
S->top=-1;
S->array=(char *)malloc(sizeof(char)*c);
return S;
}
Stack makeEmpty(void)
{
Stack *S1=create(100);
S1[0]->top=-1;
return S1;
}
char pop(Stack S)
{
return S->array[S->top--];
};
int main(void)
{
Stack *S1;
S1=makeEmpty();
int j;
int k=0;
char result[30];
for(j=0; j<2; j++)
{
char result1=pop(S1);
strcat(result, result1);
k++;
}
}
I skipped some parts, like typedef struct stack Stack;
What I wanted to do was pop out elements from the stack while for-loop works. Then, store those elements in a new array which is result. To check whether it works or not, I printed out but I had a runtime error. How to store the element and how to print it out?
I've made copy&paste of your code, and it doesn't get compiled. I think that
you are either not posting your actually code nor you don't bother to compile and read the compiler warnings. It's rather difficult to help you. Here some things I noticed:
1.
create must return a pointer to Stack, not the object.
Stack *create(int c)
{
Stack *S = malloc(sizeof *S);
S->size=c;
S->top=-1;
S->array = malloc(c);
return S;
}
2.
Same goes for makeEmpty
Stack *makeEmpty(void)
{
Stack *S1=create(100);
S1->top=-1;
return S1;
}
3.
pop should get a pointer to Stack, not the object
char pop(Stack *S)
{
return S->array[S->top--];
};
Here you should check whether there are elements on your stack. int pop(Stack *S, char *val) where it returns 1 and writes on *val on
success, and returns 0 otherwise would be better.
4.
Judging from your pop you are pushing char only. I don't get what you
are trying to do with strcat. Either way, you are doing strcat wrong. You
are declaring a stack with 100 spaces, but you are only declaring 30 spaces
for result. What if you have more than 31 elements on your stack? I know
that you are only inspecting 2 elements but it's easy to overlook that and
expand it to go through all the stack without changing the memory requirements
for result.
Also strcat is a function that works with C-Strings, that means it expects
C-Strings. A C-String must be \0 terminated, yours are not. You have
something that looks like a C-String but it's not. If you insist on using
strcat, the you should do it like this:
for(j=0; j<2; j++)
{
char result1[] = { pop(S1), 0 };
strcat(result, result1);
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Say I have a program that allocates a chunk of memory
char* get_date() {
char* date = malloc(100);
return date;
}
And I want to call the function a considerable number of times in the main function.
int main() {
int i;
for (i = 0; i < 10000; i++) {
char *c = get_date();
//do something
free(c);
}
return 1;
}
How can I reduce the number of times a new chunk of memory is allocated and just allocate one and overwrite it afterwards?
Somebody told me about something like this:
char *date = malloc(100);
for (i = 0; i < 10000; i++) {
char *c = get_date(date):
//do something
}
free(date);
But I am not sure how the new function, get_date should look like and why it should work.
Instead of having get_date return a pointer to the buffer with the data produced by the function, make it take a pointer to a buffer into which the data will be written. I.e. the prototype of get_date could be something like
void get_date(char *buf);
However, it might be useful for get_date() to be able to tell not only the starting address of the buffer but also the size of the buffer . That way,
the function can tell if the given buffer is too small (and then return e.g. an int indicating an error code). Hence, the prototype
int get_date(char *buf, size_t len);
might be more useful in practice.
On the caller side, you could then use e.g.
char date[100];
for (i = 0; i < 10000; i++) {
// return value 0 means success
if (get_date(date, sizeof date) == 0) {
//do something
}
}
I.e. in this case, you wouldn't need malloc or free at all.
You are trying to save 10,000 malloc / free calls?
Before you change your code, measure how long it takes. If you are too lazy to measure it, then the speed is not important, so don't change it.
100 bytes? Why are you using malloc() at all?
for (i = 0; i < 10000; i++) {
char c[100]:
//do something
}
If you have a function that returns temporary fixed size memory, the memory can be static:
thread_local char get_date_buffer [100];
char* get_date() {
// change get_date_buffer...
return get_date_buffer;
};
You must not free the return value and you must copy the data when reusing it and recalling the function. Many api-functions use this technique, like glGetString.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I want to define a 2D array with size 20*100000 in C. I do not want to keep the size fixed.
double **twod = malloc(20 * sizeof(double *));
int i;
if (twod == NULL)
abort();
for (i = 0; i < 20; ++i)
if ((twod[i] = malloc(100000 * sizeof(double))) == NULL)
abort();
// clean up
for (i = 0; i < 20; ++i)
free(twod[i]);
free(twod);
The first malloc call allocates space for 20 double pointers. Each double pointer will point to a subarray.
The second malloc call in the loop allocates 100000 doubles in each subarray.
The free calls do the inverse of malloc--they return memory to free store. First, each subarray must be freed, in a loop. Then the entire array itself must be freed too.
The return value of malloc is examined against NULL. If malloc returns NULL, then the system is out of memory. This is important since you are allocating HUGE amounts of memory. If malloc returns NULL, the application is aborted.
You'll need to define a pointer to pointer and initialize it like this:
int i;
double **array;
array = malloc(sizeof(double *)) * 20);
for (i=0; i<20; i++) {
array[i] = malloc(sizeof(double) * 100000);
}
Don't forget to free the memory when you're done with it.
You can use a Variable-length array (since C99) in order to avoid fragmentation:
double (*array)[cols];
array = malloc(sizeof(*array) * rows);
In this way calling free(array); is enough.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I have a file which contains a set of numbers.
I'm trying to read those numbers into an array. I'm allocating memory for that array using a pointer and reading from the file into the location.
For some reason, the program does not read beyond 5 values from the file.
int main(int argc, char* argv[] )
{
int i=0, count=0;
//unsigned long int num[1000];
unsigned long int *ptr;
ptr = (unsigned long int*) malloc (sizeof(unsigned long int));
char file1[30], file2[30];
int bin[1000][32];
int ch;
argv++;
strcpy(file1,*argv);
FILE *fp;
fp=fopen(file1, "r");
while((fscanf(fp,"%ld",ptr))==1)
{
ptr++;
count++;
}
ptr=ptr-count;
for(i=0; i<count;i++,ptr++)
printf("%ld\n",*ptr);
return 0;
}
The input file contains the following:
1206215586
3241580200
3270055958
2720116784
3423335924
1851806274
204254658
2047265792
19088743
The output is just this:
1206215586
3241580200
3270055958
2720116784
3423335924
Thanks in advance.
You need to allocate enough space to store your integers in. To do this , use the realloc function on the original pointer.
The fact that you write ptr++ makes it awkward to call realloc on the original pointer and save the result. So it would be a better idea to not use ptr++. Instead you can use ptr[count] and leave ptr always pointing to the start of the allocation.
For example the main loop could be:
while((fscanf(fp,"%lu",&ptr[count]))==1)
{
count++;
void *new = realloc(ptr, (count+1) * sizeof(*ptr));
if ( !new )
break; // maybe print error message, etc.
ptr = new;
}
// don't do this any more
// ptr=ptr-count;
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
So, this is working fine... that means, no compiler errors, it seems that there is no memory leak and it is doing what I wanted it to do. That said should it be working? When I go to books_init I send a local variable to collection, doesn't it mean that when I go back to main it shouldn't be working? (or undefined behavior?). Also, in case you say that I have to malloc it, do I have to free it after? (commented on cleanup)
/* pseudo struct Collection{
size_t size, capacity;
Volume *volumes;
} */
void collection_init(Collection *col, size_t capacity){
col->size = 0;
col->capacity = capacity;
col->volumes = malloc(sizeof(Volume) * capacity);
}
void collection_resize(Collection *col, size_t capacity){
Volume *v = realloc(col->volumes, capacity * sizeof(Volume));
if(!v) return;
col->capacity = capacity;
col->volumes = v;
}
void collection_add(Collection *col, Volume *volume){
if(col->size >= col->capacity)
collection_resize(col, col->capacity * 2);
col->volumes[col->size++] = *volume;
}
void collection_clean(Collection *col){
//for(vol : col->vol) free(vol);
//should I free every element or just volumes?
free(col->volumes);
}
void books_init(Collection *col){
for(int i = 0; i < 25; ++i){
Volume v = {.swag = i};
collection_add(col, &v);
}
}
int main(){
Collection col;
collection_init(&col, 10);
books_init(&col);
for(int i = 0; i < col.size; ++i){
printf("\tVol[%d].id = %d\n", i, col.volumes[i].swag);
}
collection_clean(&col);
return 0;
}
Thanks for your time
This line in books_init
Volume v = {.swag = i};
creates a local variable called v with member swag initialized to i. The address of that variable is then passed to collection_add. That is allowed because v is still in scope.
This line in collection_add
col->volumes[col->size++] = *volume;
makes a copy of the contents of the Volume structure, and stores that copy in the memory that was allocated in collection_init.
After collection_add returns, the variable v in books_init goes out of scope, but that's OK because the contents of v were copied and saved in the memory that col->volumes points to.
When the program ends, collection_clean only needs
free(col->volumes);
to remove all of the Volume copies from memory.
The only flaw I see in your program occurs if realloc fails. In that case, you still write to the Volume array. This will cause a buffer overrun and memory corruption. To avoid this, the collection_add function should verify that the collection_resize function succeeded before performing the copy. For example, you could check again that col->capacity > col->size before doing the copy.
TL;DR your code is fine as long as the realloc always succeeds.