Segmentation fault in C, malloc array - c

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.

Related

c Segmentation fault in macOS ; sometimes, and sometimes not

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.

Calloc/Malloc and freeing to often or too large a space?

Disclaimer, this is help with a school assignment. That being said, my issue only occurs about 50% of the time. Meaning if I compile and run my code without edits sometimes it will make it through to the end and other times it will not. Through the use of multiple print statements I know exactly where the issue is occurring when it does. The issue occurs in my second call to hugeDestroyer(right after the print 354913546879519843519843548943513179 portion) and more exactly at the free(p->digits) portion.
I have tried the advice found here (free a pointer to dynamic array in c) and setting the pointers to NULL after freeing them with no luck.
Through some digging and soul searching I have learned a little more about how free works from (How do malloc() and free() work?) and I wonder if my issue stems from what user Juergen mentions in his answer and that I am "overwriting" admin data in the free list.
To be clear, my question is two-fold.
Is free(p->digits) syntactically correct and if so why might I have trouble half the time when running the code?
Secondly, how can I guard against this kind of behavior in my functions?
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct HugeInteger
{
// a dynamically allocated array to hold the digits of a huge integer
int *digits;
// the number of digits in the huge integer (approx. equal to array length)
int length;
} HugeInteger;
// Functional Prototypes
int str2int(char str) //converts single digit numbers contained in strings to their int value
{
return str - 48;
}
HugeInteger *parseInt(unsigned int n)
{
int i = 0, j = 0;
int *a = (int *)calloc(10, sizeof(int));
HugeInteger *p = (HugeInteger *)calloc(1, sizeof(HugeInteger));
if(n == 0)
{
p->digits = (int *)calloc(1, sizeof(int));
p->length = 1;
return p;
}
while(n != 0)
{
a[i] = n % 10;
n = n / 10;
i++;
}
p->length = i;
p->digits = (int *)calloc(p->length, sizeof(int));
for(i = 0; i <= p->length; i++, j++)
p->digits[j] = a[i];
return p;
}
HugeInteger *parseString(char *str) //notice datatype is char (as in char array), so a simple for loop should convert to huge int array
{
int i = 0, j = 0;
HugeInteger *p = (HugeInteger *)calloc(1, sizeof(HugeInteger));
if(str == NULL)
{
free(p);
p = NULL;
return p;
}
else
{
for(i=0; str[i] != '\0'; i++)
;
p->length = i;
p->digits = (int *)calloc(p->length, sizeof(int));
for(; i >= 0; i--)
p->digits[j++] = str2int(str[i - 1]);
}
return p;
} //end of HugeInteger *parseString(char *str)
HugeInteger *hugeDestroyer(HugeInteger *p)
{
//printf("No problem as we enter the function\n");
if(p == NULL)
return p;
//printf("No problem after checking for p = NULL\n");
if(p->digits == NULL)
{
free(p);
p = NULL;
return p;
}
//printf("No Problem after checking if p->digits = NULL\n");
//else
//{
free(p->digits);
printf("We made it through free(p->digits)\n");
p->digits = NULL;
printf("We made it through p->digits = NULL\n");
free(p);
printf("We made it through free(p)\n");
p = NULL;
printf("We made it through p = NULL\n");
return p;
//}
//return NULL;
}//end of HugeInteger *hugeDestroyer(HugeInteger *p)
// print a HugeInteger (followed by a newline character)
void hugePrint(HugeInteger *p)
{
int i;
if (p == NULL || p->digits == NULL)
{
printf("(null pointer)\n");
return;
}
for (i = p->length - 1; i >= 0; i--)
printf("%d", p->digits[i]);
printf("\n");
}
int main(void)
{
HugeInteger *p;
hugePrint(p = parseString("12345"));
hugeDestroyer(p);
hugePrint(p = parseString("354913546879519843519843548943513179"));
hugeDestroyer(p);
hugePrint(p = parseString(NULL));
hugeDestroyer(p);
hugePrint(p = parseInt(246810));
hugeDestroyer(p);
hugePrint(p = parseInt(0));
hugeDestroyer(p);
hugePrint(p = parseInt(INT_MAX));
hugeDestroyer(p);
//hugePrint(p = parseInt(UINT_MAX));
//hugeDestroyer(p);
return 0;
}
First of all, really outstanding question. You did a lot of research on topic and generally speaking, solved this issue by yourself, I'm here mainly to confirm your findings.
Is free(p->digits) syntactically correct and if so why might I have trouble half the time when running the code?
Syntax is correct. #Shihab suggested in comments not to release p->digits and release p only, but such suggestion is wrong, it leads to memory leakages. There is a simple rule: for each calloc you must eventually call free, so your current approach in freeing p->digits and then p is totally fine.
However, program fails on a valid line. How is it possible? Quick answer: free can't do its work due to corruption of meta information responsible for tracking allocated/free blocks lists. At some point program corrupted meta information, but this was revealed only on attempt to use it.
As you already discovered, in most implementations memory routines such as calloc results into allocation of buffer with prepended meta-info. You receives pointer to buffer itself, but small piece of information right before this pointer is crucial for further buffer managing (e.g. freeing). Writing 11 integers into buffer intended for 10, you're likely to corrupt meta-info of block following the buffer. Whether corruption actually happens and what would be its consequences, is heavily dependent on both implementation specifics and current memory alignment (what block follows the buffer, what exactly meta-data is corrupted). It doesn't surprise me, that you see one crash per two executions, neither surprises me observing 100% crash reproduction on my system.
Secondly, how can I guard against this kind of behavior in my functions?
Let's start with fixing overflows. There are couple of them:
parseString: loop for(; i >= 0; i--) is executed length+1 times, so p->digits is overflown
parseInt: loop for (i = 0; i <= p->length; i++, j++) is executed length+1 times, so p->digits is overflown
Direct access to memory managing in C++ is error prone and troublesome to debug. Memory leakages and buffers overflows are the worst nightmare in programmers life, it's usually better to simplify/reduce direct usage of dynamic memory, unless you are studying to cope with it, of course. If you need to stick with a lot of direct memory managing, take a look at valgrind, it's intended to detect all such things.
By the way, there is also a memory leakage in your program: each call to parseInt allocates buffer for a, but never frees it.

Change a dynamic 2D char array through a function in C?

I'm creating this sample run so I can better understand how I can edit dynamic arrays through other functions, but I started running into segfaults once I added the secondary function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void other_side(char ***funk);
int main()
{
int i;
char *argv[11] = {"fish", "dish", "lags", "fags", "shag", "cool", "bean", "rekt", "noon", "coon", "lolz"};
char **yep, **nop;
yep = malloc(10 * sizeof *yep);
if(!yep) { // <-----------------added check for malloc error
printf("Error: failure to allocate memory\n");
exit(1);
}
printf("10 times %lu\n\n", sizeof *yep);
for(i = 0; i<10; i++) {
yep[i] = strdup(argv[i]);
printf("%s is in yep.\n", *(yep+i));
}
nop = realloc(yep, 11 * sizeof *yep); //you reallocate to the new total size.
if(nop == NULL) {
printf("Error: failure to allocate memory\n")
exit(1);
}
yep = nop;
*(yep+10) = strdup(argv[10]);
printf("Last but certainly not least, %s is in yep.\n", *(yep+10));
printf("Now to send yep over to the other side and have its values changed.\n");
other_side(&yep);
printf("Did it change?\n\n");
for(i=0; i<11; i++)
printf("%s is in yep.\n", *(yep+i));
for(i=0; i<11; i++) { //issue fixed when added strdup() above, previously static
free(*(yep+i));
}
free(yep);
return 0;
}
void other_side(char ***funk)
{
char *arr[11] = {"dude","yeah","gnar","nice","epic","need","more", "word","four","this","test"};
int i;
for(i=0; i<11; i++) {
**(funk+i) = strdup(arr[i]); //added strdup() here as well
printf("%s is currently in yep.\n", **(funk+i));
}
printf("\n");
}
A couple things I noticed with this is that Valgrind notices an unnecessary free when I try to free the 11th block of memory to my array in main(). I'm not sure if that's my issue, but I also noticed that the function will only change two words before it leads to a segmentation fault.
Edit Notes: Since the edit I still get segfaults, but valgrind has been a bit more clear with what is happening. (Bad permissions for mapped region at address 0x400B18)
Your order of precedence regarding operators is important, and you missed a pair of parens to ensure it is done correctly. This: **(funk+i) means this: *(funk[i]), not (*funk)[i] which is what you want.
This:
**(funk+i) = strdup(arr[i]);
printf("%s is currently in yep.\n", **(funk+i));
Should be this:
*((*funk)+i) = strdup(arr[i]);
printf("%s is currently in yep.\n", *((*funk)+i));
and frankly, it is considerably easier to read as:
(*funk)[i] = strdup(arr[i]);
printf("%s is currently in yep.\n", (*funk)[i]);
I leave the rest of the memory management to you to fix. (i.e. the leaks from the dynamic memory pointed to by all the pointers you're overwriting in the above loop code).

Segmentation fault after realloc(). Can't assign allocated memory to pointer

I'm trying to allocate some memory with realloc(). This works so far. But if I want to assign the allocated memory to a pointer in a struct variable, I get a segmentation fault:
// in header
typedef struct {
int a;
char test[20];
} MyContent;
typedef struct {
MyContent* values;
// simmilar to: MyContent values[]
// ... some other stuff
} MyData;
// in source
void myFunction(MyData* dataPtr) {
dataPtr->values = NULL;
MyData* tempPtr = NULL;
for (int i = 1; i < 10; i++) {
tempPtr = (MyContent*) realloc(dataPtr->values, i * sizeof(MyContent));
if (tempPtr == NULL) {
free(dataPtr->values);
break;
}
dataPtr->values = tempPtr; // Here I get the segmentation fault
dataPtr->values[(i-1)].a = 42;
// ...
}
}
I can't figure out what's going wrong here. Any suggestions? Thanks for your help.
Seems like you edited your code. The edited code works just fine.
#include<stdio.h>
#include<malloc.h>
#include<string.h>
// in header
typedef struct {
int a;
char test[20];
} MyContent;
typedef struct {
MyContent* values;
// simmilar to: MyContent values[]
// ... some other stuff
} MyData;
// in source
void myFunction(MyData* dataPtr) {
dataPtr->values = NULL;
MyData* tempPtr;
for (int i = 1; i < 10; i++) {
tempPtr = (MyData*) realloc(dataPtr->values, i * sizeof(MyContent));
if (tempPtr == NULL) {
if(dataPtr->values)
free(dataPtr->values);
printf("realloc() failed\n");
return ;
}
dataPtr->values = (MyContent*)tempPtr; // Here I get the segmentation fault
dataPtr->values[(i-1)].a = 42+i;
strcpy(dataPtr->values[(i-1)].test,"name");
}
}
void PrintData(MyData* dataPtr) {
for (int i = 1; i < 10; i++)
printf("We have %s at %d\n",dataPtr->values[(i-1)].test,dataPtr->values[(i-1)].a);
}
main() {
MyData Sample;
myFunction(&Sample);
PrintData(&Sample);
}
At first glance, I don't see a problem that could cause a crash there - that ones-based addressing is a bit odd, but not incorrect. There could be a problem in the code that you're not showing that results in heap or stack corruption that the realloc call makes worse. Or if you are compiling with optimizations, your debugger might be confused about where the crash is actually occurring. You're also confusing MyData and MyContent, but I'll assume that's just because you made an error while redacting the code.
Note also that if realloc fails, you will crash on the line after the one you indicated, as you'll be writing to a null pointer. You need to abort if tempPtr is NULL, not just free the old pointer. Again, though, this causes a fault on a different line than you indicated.
I'd recommend running your program under valgrind to see where it reports errors - the first such error to occur is likely to be the culprit.
Your condition is wrong for checking the newly allocated memory. It should be:
if (tempPtr == NULL) {
// handle error condition or continue with original 'dataPtr->values'
}
else {
dataPtr->values = tempPtr;
}
Remember that realloc() doesn't necessarily transfer one block to the another block. Sometimes it may allocate the memory in the same pointer region.

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