c Segmentation fault in macOS ; sometimes, and sometimes not - c

void makeDouble(int **a, int *size){
int i, j;
*size *= 2;
*a = (int *)realloc(*a, (*size)*sizeof(int));
for(i=0; i<*size/2; i++){
(*a)[*size/2+i] = (*a)[i] * 2;
}
int temp;
for(i=0; i<*size-1; i++){
for(j=0; j<*size-i-1; j++){
if((*a)[j]>(*a)[j+1]){
temp = (*a)[j];
(*a)[j] = (*a)[j+1];
(*a)[j+1] = temp;
}
}
}
}
$
this is my code. What I wanted to do is getting a size and input as size, then making them all doubled, and sorting them.
But when I compile this, sometimes it collapses with segmentation fault and sometimes doesn't. And sometimes, it says "malloc: * error for object 0x7fda70c02730: incorrect checksum for freed object - object was probably modified after being freed.
* set a breakpoint in malloc_error_break to debug
Abort trap: 6"
Why and What can I do with this? Sorry if my question is bad, I'm beginner with c.

First Segfault
One place where this would cause a segfault for sure is:
int size;
scanf("%d", &size);
int* a = (int *)malloc(size*sizeof(int));
if you pass it a character instead of a number that fits into an integer this would fail, because scanf is not gonna write to size.
You have to check the return of scanf which is the number of input items successfully matched:
if (scanf("%d", &size) != 1) {
fprintf(stderr, "Supplied size is not a valid number.\n");
return 1;
}
Memory Leak
if realloc returns NULL because it failed to allocate enough space, you get a memory leak because you do:
int *a = realloc(a, ...);
This pattern is buggy, because assigning the return of realloc to the array you wanna reallocate means you lose the reference to the allocated array since a == NULL. Do:
int *temp = realloc(a, ...);
if (temp == NULL) {
free(a); // Or continue using it ..
} else {
a = temp;
}
Heap Corruption
Your function makeDouble is causing a heap corruption because you're accessing and modifying out of bound memory. I'm getting a realloc() abort: invalid next size with glibc, so you're most likely smashing the heap already allocated by the runtime, but not reaching the next page, hence no Segfault and a runtime error instead.

Related

Logical error while using realloc() function

I am using dynamic memory allocation in C for a simple problem that I am trying to solve. It involves taking user input for the elements of 2 arrays. I was thinking that I will initialise the array to a large size and use realloc to reduce the size once the input has been completed. ?below is the code for same:
void arrayop()
{
int val, i=0;
int *arr1 = (int*) calloc(100,sizeof(int));
int *arr2 = (int*) calloc(100,sizeof(int));
printf("Enter first array:(-1 to stop)\n");
while(val!=-1)
{
if(val != -1)
{
scanf("%d",&val);
*(arr1 + i) = val;
i++;
}
}
//printf("\t%d\n",i);
arr1 = (int*)realloc(arr1,(i));
//printf("\t%d\n",(sizeof(arr1)));
for(int j=0;j<i;j++)
{
printf("%d ",*(arr1 + j));
}
printf("\n");
}
However, realloc() is somehow overwriting already entered elements and filling them with garbage value. Can anyone give me any insight as to why this is happening, or where I am wrong?
realloc expects the allocation size, but you're telling it how many ints you want. When you call it like this:
arr1 = (int*)realloc(arr1,(i));
i holds the number of ints that you want to allocate space for, but the actual size needed for the allocation is i * sizeof(int), so to fix it you need:
arr1 = realloc(arr1, sizeof(int) * i);
Or, even better:
arr1 = realloc(arr1, sizeof(*arr1) * i);
The second variant will work even if you change the type of arr1 from int * to, say, short *.
You may also want to check the pointer returned by realloc and make sure the allocation succeeded. Note that if realloc fails, arr1 won't be freed and you'll end up leaking it. A better approach is:
int *temp = realloc(arr1, sizeof(*arr1) * i);
if (temp == NULL)
{
fprintf(stderr, "realloc failed\n");
free(arr1);
return;
}
arr1 = temp;
While we're at it, don't cast the result of malloc, calloc, or realloc. See Do I cast the result of malloc?
.

Deallocating 2D array in C

For whatever reason I am getting the following error when trying to free the 2D array I created:
Error in `./a.out': free(): invalid next size (fast): 0x0000000001759310 *** Aborted (core dumped)
I printed out the contents of the array and they are correct and I am able access all of the elements. However, I am yet to be able to free it. The error occurs when going through the freeing loop, i.e. freeing double *. Would appreciate any help.
Thanks!
Here is the code:
/*allocation*/
double **block_mat = (double **) malloc (sizeof(double *) * num_blocks);
int i;
for (i = 0; i <num_blocks; i++){
block_mat[i] = (double *) malloc (sizeof(double) * s);
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free(block_mat[i]);
}
free(block_mat);
EDIT:
The error was found! I under-allocated memory...So when I printed out my arrays they looked like everything was fine... I allocated arrays of sizes s, but used s^2 instead. Thank you everyone!
You allocate space for s doubles for each block_mat[i]. Later, you access
block_mat[i][block_index] = 0;
block_index++;
but you never check that block_index goes out of bounds, which it does.
If you write beyond the s allocated doubles, you might corrupt the internal control data for the subsequent pointer, which usually is placed before the pointer returned by malloc and which is required to be intact by free.
Are you sure that these pointers were all allocated with distinct mallocs?
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
free(my_matrix);
for (i = 0; i < num_blocks; i++){
free(block_mat[i]);
}
free(block_mat);
If two of them are the same pointer, then you are trying to free something twice.
This is incorrect:
free(my_matrix);
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
The order should be at least like this:
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
free(my_matrix);
You have several problem that can impact allocation. The first, what if the call to strtol fails?
s = (int)strtol(argv [3], &ptr, 10);
You should check the conversion:
#include <errno.h>
...
else {
errno = 0;
long tmp = strtol(argv [3], &ptr, 10);
if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
(errno != 0 && tmp == 0)) {
perror ("strtol");
exit (EXIT_FAILURE);
}
if (ptr == argv[3]) {
fprintf (stderr, "No digits were found\n");
exit (EXIT_FAILURE);
}
s = (int)tmp;
}
Next, with your allocation and free, you were on the right track, but don't cast the return of malloc. Casting the return only increases the chance of a hard to debug error. When allocating a pointer-to-pointer-to-double, you need to allocate as many pointers as needed. (num_blocks) in your case. When computing the size of the allocation, you can simply dereference the variable being allocated which again lessens the chance of error:
int i;
double **block_mat = malloc (sizeof *block_mat * num_blocks);
/* check allocation for failure */
for (i = 0; i <num_blocks; i++){
block_mat[i] = malloc (sizeof **block_mat * s);
/* check allocation for failure */
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free (block_mat[i]);
}
free(block_mat);
Note: you must initialize all values in block_mat before you begin referencing the elements to prevent the deference of an unassigned value later. (e.g. double result = block_mat[i][j] * Pi;) Consider adding:
block_mat[i] = malloc (sizeof **block_mat * s);
/* check for failure */
block_mat[i] = 0.0;
Note: When allocating numerical matricies, consider using calloc instead of malloc as it will initialize all values to '0' and prevent the inadvertent dereference of an unassigned valued -- which is undefined behavior. Using calloc you would have:
int i;
double **block_mat = calloc (num_blocks, sizeof *block_mat);
/* check allocation for failure */
for (i = 0; i <num_blocks; i++){
block_mat[i] = calloc (s, sizeof **block_mat);
/* check allocation for failure */
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free (block_mat[i]);
}
free(block_mat);
Note: when s is greater than 1, you will alloc space for more than one double at each pointer. Noting prevents you from doing that, but you are responsible for handling the offset to each value. (e.g. result = *(block_mat[i] + j + n * sizeof **block_mat) * Pi;, where n is 0 <= n < s) If you are storing multiple doubles in each pointer, consider using a pointer-to-struct instead. E.g.:
typedef struct point {
double x;
double y;
double z;
} point;

Segmentation fault in C, malloc array

I have problem with my school project, the server which is testing this build returns this error:
./__runscript: line 2: 489 Segmentation fault ./a.out < __input
Compile is OK, but this error is displayed just when it starts running. But if I run it on Windows 7 with visual studio 10, everything is fine. I think the mistake might be in the insert() function.
POSTUP *insert(POSTUP *first)
{
POSTUP* current,*pom;
current=(POSTUP*)malloc(sizeof(POSTUP));
pom=(POSTUP*)malloc(sizeof(POSTUP));
int i,count_of_elements;
scanf("%d", &count_of_elements);
if(first==NULL)
{
first=current;
first->array= (int*)malloc(count_of_elements*sizeof(int));
for(i=0; i<count_of_elements; i++)
{
scanf("%d",&first->array[i]);
}
first->elements=count_of_elements;
first->next=NULL;
return first;
}
else
{
pom->array= (int*)malloc(count_of_elements*sizeof(int));
for(i=0; i<count_of_elements; i++)
{
scanf("%d",&pom->array[i]);
}
pom->next=NULL;
pom->elements=count_of_elements;
current=first;
while(1)
{
if(current->next==NULL)
{
current->next=pom;
return first;
}
}
}
return 0;
}
int main(void)
{
int count, i;
POSTUP* first,*current;
first= (POSTUP*)malloc(sizeof(POSTUP));
first=NULL;
scanf("%d",&count);
for(i=0; i<count; i++)
{
first=insert(first);
}
}
This code in main():
POSTUP *first, *current;
first = (POSTUP*)malloc(sizeof(POSTUP));
first = NULL;
scanf("%d", &count);
for (i = 0; i < count; i++)
{
first = insert(first);
}
is clearly problematic. You allocate space and store the only pointer to it in first; you then overwrite the pointer, leaking memory. You should officially check that the allocation was not null. But your insert() code is equipped to handle a null pointer as input, so the memory allocation in main is redundant.
In insert(), you allocate memory without checking for success; this is a recipe for trouble, though more usually later than sooner.
Your code is never checking the result of scanf(); that means you could be getting rubbish into your system if there's a format error in the data.
Likely cause of crash: In the 'if (first == NULL)block ininsert()`, you have:
for(i=0; i<count_of_elements; i++)
{
scanf("%d", &prvy->array[i]);
}
There's no declaration of prvy in sight in the code you show; it should almost certainly be referring to &first->array[i] anyway. This could easily be good for a crash. Otherwise, you've carefully stashed the data in a different set of memory than you thought, so the array for first is uninitialized gibberish.
The same code does not use pom, so you've leaked memory in this part of the code.
In the main else clause in insert(), you overwrite current (which contained a memory allocation) with first, thus leaking memory there too.
Don't allocate memory until you're about to use it.

Find a memory leak in C

I'm trying to find a memory leak in the folowing code. valgrind gives me this:
==14160== 1,850 (592 direct, 1,258 indirect) bytes in 9 blocks are definitely lost in loss record 2 of 5
==14160== at 0x4904A06: malloc (vg_replace_malloc.c:149)
==14160== by 0x405B1F: tsCreate (ticket_set.c:55)
==14160== by 0x401ECA: test1TS (main.c:62)
==14160== by 0x40557C: main (main.c:424)
and here's the function:
TicketSetStatus tsCreate(TicketSet* t, int n, int c) {
if(t==NULL){
return TS_CANNOT_CREATE;
}
if (n <= 0){
return TS_ILLEGAL_PARAMETER;
}
t->usedTravels = 0;
t->originalTravels = n;
t->cost = c;
t->moneyLeft = n * c;
//Date time is array of travels:
t->dates = malloc(sizeof(DateTime *)* (n)); //todo maybe c99 allows dynamic arrays?
for (int i = 0; i < n; i++) {
t->dates[i] = malloc(sizeof(char)*GOOD_LENGTH+1);
if (t->dates[i] == NULL) {
free( t->dates);
return TS_CANNOT_CREATE;
}
}
return TS_SUCCESS;
}
TicketSetStatus tsDestroy(TicketSet* t, int* moneyLeft) {
if (t == NULL) {
return TS_FAIL;
}
*moneyLeft = (t->cost) * (t->originalTravels-t->usedTravels);
for (int i = 0; i < t->originalTravels; i++){
free(t->dates[i]);
}
free(t->dates);
t=NULL;
return TS_SUCCESS;
}
when the struct is:
struct TS_element {
int usedTravels;
int originalTravels;
int cost;
DateTime* dates;
int moneyLeft;
};
and
typedef char* DateType
actually playing with free crashes the program more often than not so i'm inclined to live with the memory leak as long as the program functions correctly.
How are you using this array of DateTime? If you are stomping on the values later you will get leaks. Perhaps a confusion about string assignment? ie
char someDateValue[] = "2012-08-15";
t->dates[0] = someDateValue; // Leak -- your allocated string is lost
Instead:
strcpy( t->dates[0], someDateValue );
There is a definite leak in your error condition in tsCreate:
for (int i = 0; i < n; i++) {
t->dates[i] = malloc(sizeof(char)*GOOD_LENGTH+1);
if (t->dates[i] == NULL) {
free(t->dates); // Leak -- every element up to i-1 is lost
return TS_CANNOT_CREATE;
}
}
Are you calling tsDestroy after you've finished with data initialised by tsCreate? Perhaps you're returning from main without cleaning up.
If none of this helps, you should post additional code to show how you are using your data structure.
For at least one error you can focus solely on
...
t->dates = malloc(sizeof(DateTime*) * (n)); /* first malloc */
for (int i = 0; i < n; i++) { /* call this loop 1 */
t->dates[i] = malloc(sizeof(char)*GOOD_LENGTH+1); /* second malloc */
if (t->dates[i] == NULL) { /* test for malloc error */
free( t->dates); /* free the base array/list */
return TS_CANNOT_CREATE; /* exit function */
}
}
...
The problem is if the second malloc fails, the free only frees the base (first) malloc. It does not free any other memory allocations created by the second malloc
in loop 1, on a previous loop 1 iteration. I.e. if t->dates[i] = malloc(... fails when i is equal to 5 then the memory blocks allocated in the iterations 0 to 4 are not freed before exiting the function.
Hopefully that makes sense.
Update #paddy is correct in noting the error of t->dates[0] = someDateValue
which in this case what that is saying is:
char someDateValue[] = "2012-08-15";
could also be written in this case as
char *someDateValue = "2012-08-15";
so that
t->dates[0] = someDateValue;
simply assigns the pointer of the string, replacing the pointer to the freshly allocated block in the preceding malloc.
Ref: If you are still confused you can read the C FAQ question 6.3 So what is meant by the ``equivalence of pointers and arrays'' in C? as well as the rest of the C FAQ.
And is correct to suggest str[n]cpy (or similar replacements) to copy the array contents (rather than its pointer) to the freshly allocated memory block.

Freeing Object Error

I am mallocing an array of c strings. After releasing it, I get the following error:
Assembler(87536) malloc: *** error for object 0x108500840: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Why is that? I am pretty sure I am doing the malloc correctly. I'm pretty experienced with memory management, but I am not sure why this is giving me an error. The array is should hold three strings, each of which is 2 characters long.
Here is how I am mallocing the array:
char **reg_store;
reg_store = malloc(3 * (sizeof(char*)));
if (reg_store == NULL) {
fprintf(Out, "Out of memory\n");
exit(1);
}
for (int i = 0; i < 3; i++) {
reg_store[i] = malloc(2 * sizeof(char));
if (reg_store[i] == NULL) {
fprintf(Out, "Out of memory\n");
exit(1);
}
}
Here is how I am freeing it:
for (int i = 0; i < 3; i++) {
free(reg_store[i]);
}
free(reg_store);
Here is what I have in between:
// Keeps a reference to which register has been parsed for storage
int count = 0;
char *reg = NULL;
char *inst_ptr // POINTS TO SOME STRING. EXAMPLE: $t2, $t1, $a0
while (1) {
// Parses the string in inst_ptr with dollar, comma and space as a delimiter.
reg = parse_token(inst_ptr, " $,\n", &inst_ptr, NULL);
if (reg == NULL || *reg == '#') {
break;
}
reg_store[count] = reg;
count++;
free(reg);
}
I am printing out reg after I call parse_token and it does print out correctly. I am also printing out reg_store[count] and it does also print out correctly.
Your problem is here:
reg_store[count] = reg;
free(reg);
and later
free(reg_store[i]);
reg is already freed and you free it another time (not talking about the problems with using it later). to fix this replace
reg_store[count] = reg;
with
strcpy(reg_store[count], reg);
or as suggested in the comments, since you know its two charaters, its better to memcpy it:
memcpy(reg_store[count], reg, 2);
I would suggest adding some printfs (or use the debugger) to see the values of all the malloced pointers just after they have been malloced. Then do the same just before they are freed, to make sure they are the same. Perhaps there is some other rogue code elsewhere in the program that is stomping over memory.
Your problem is in the "in between" code, in particular, right here:
reg_store[count] = reg;
count++;
free(reg);
You allocated reg_store[count] with malloc during your set up, then you overwrite the allocated value with reg and then free reg. The result is a memory leak from the original pointers that were in reg_store and a double-free on each element of reg_store when you try to clean everything up.
You need to copy reg into the memory already allocated in reg_store[count] (watching the size of course) or don't allocate any space for the elements of reg_store before the "in between" code at all.
The error was already pointed out so no need to write it again.
I can however point out that i don't like the way you are handling errors.
void freeRegStore(char** reg_store)
{
int i;
if (reg_store != NULL)
{
for (i = 0; i < 3; i++)
free(reg_store[i]);
free(reg_store);
}
}
char** allocRegStore()
{
int i;
char **reg_store;
reg_store = calloc(3 * (sizeof(char*)), 1);
if (reg_store != NULL)
{
for (i = 0; i < 3; i++)
{
reg_store[i] = malloc(2 * sizeof(char));
if (reg_store[i] == NULL)
{
freeRegStore(reg_store);
return NULL;
}
}
}
return reg_store;
}
In this method, the function allocRegStore will return NULL if there was not enough memory without leaving pieces around.
Then you can handle this case in main and not in the allocation function itself.
I disagree with the use of printf and exit inside functions.
int main()
{
char** reg_store = allocRegStore();
if (reg_store == NULL)
{
puts("Out of memory");
return 1;
}
... do your stuff
freeRegStore();
return 0;
}
I can also say that the memory used by this program will never go out of memory :) i would not worry about that.

Resources