malloc() returning a null pointer - c

I'm attempting a C programming assignment where I need to iterate through each index of each line of a document, and set an integer value at each character index in a corresponding array ar:
//Jagged array ar containing pointers to each row
int* ar[line_count];
//The size of each row is the line width * the size of an int ptr
const int line_size = max_width * sizeof(int*);
//For each line
for (i = 0; i < line_count; i++)
{
//If the first runthrough, copy the blank array
if (i == 0)
{
ar[i] = malloc(line_size);
memcpy(ar[i], blank_ar, line_size);
}
//Otherwise, copy from the last row
else
{
ar[i] = malloc(line_size);
//This is set to a null pointer after several runthroughs
memcpy(ar[i], ar[i - 1], line_size);
}
//Edit the current row ar[i]
}
The only problem is, after some 9 iterations, malloc starts returning a null pointer that causes memcpy to (obviously) not work.
Is there any reason this is happening? There is no way I'm running out of memory as I only allocate these tiny arrays 9 times.

malloc will return the null pointer when it fails. Some obvious reasons why this could happen:
You have exhausted heap memory. That is plausible if line_size is very large.
You have corrupted the heap. That could happen if there are errors in the code that you are running, but have removed for the purpose of asking this question.
Inspect the value of errno to find out more information about the failure.

Maybe you stack is too little, try to modify the default stack at compile/linking time in your IDE. If you are using GCC take a look into this Change stack size for a C++ application in Linux during compilation with GNU compiler

Related

How to correctly allocate memory for an array of char pointers (strings of different length)?

Sorry if it sounds like a duplicate, but I have checked similar questions and to my eye my approach is correct, therefore I would like to ask you for advice.
I want to allocate the memory for an array of pointers to the first elements of char arrays (in other words: this is an array of strings). Additionally, these strings may differ in length. I use realloc() for specific char arrays in order not to allocate unnecessary memory.
Here I present the fragments of the code that seem to be troublesome for me:
#define NUM_SEQ 4
#define MIN_BUFFER 1000
#define MAX_BUFFER 10000
char** read_the_file(char* file_name) {
//opens the file
char** sequences = malloc(NUM_SEQ*sizeof(char*));
printf("all: %ld\n", sizeof(sequences)); //OUTPUT: 8
for (int i = 0; i < NUM_SEQ; i++) {
sequences[i] = malloc(MIN_BUFFER);
printf("seq %d: %ld\n", i, sizeof(sequences[i])); //OUTPUT: 8, for each of them
}
int num_of_seq = 0; //Number of the sequence in the array of sequences
int counter = 0; //Indicates the position of the character in the string
//Loop irrelevant to the problem is omitted
if (counter == sizeof(sequences[num_of_seq])) {
printf("%ld\n", sizeof(sequences[num_of_seq]));
printf("Here\n");
if (sizeof(sequences[num_of_seq])*2 < MAX_BUFFER) {
char* temp = realloc(sequences[num_of_seq], sizeof(sequences[num_of_seq])*2);
if (temp != NULL) {
sequences[num_of_seq] = temp;
} else {
printf("Allocating memory failure\n");
exit(EXIT_FAILURE);
}
} else {
printf("The sequence is too long\n");
exit(EXIT_FAILURE);
}
}
//Let this loop die in loneliness
return sequences;
}
Reallocating of the memory is a recent modification. Without it (simply allocating with malloc) the program works fine, even under valgrind. Now the results are correct, but the valgrind returns multiply times an error:
Address 0x4a5b810 is 0 bytes after a block of size 16 alloc'd
in various functions and always refer to this realloc
Another issue: the sequences don't exceed the length of 10. The counter shouldn't be equal to the size of the array, but the loop with realloc IS entered - which shouldn't have happened.
Sorry for terrible indentation, I have a problem with keeping the text in code style on this site and thank you for your much appreciated suggestions.
As #MikeCAT suggested, the issue was the improper use of sizeof(), which returns the size of the given expression or type. The solution to this problem is tracking the actual size of the object, i.e.: using the variable actual_size_of_seq1, initialized at MIN_BUFFER for the first sequence (I use an array of sizes, though).

C - Function call itself causes segfault in recursive calls

Im fighting a segfault error that I can't understand : I have a recursive function that expands on an array representing pixels : starting on an index, it exepands around the index to create groups of pixels by calling the same function left right up and down (aka index -1, index +1...). For debuging purposes, I have a printf call at the very first line of the function, and one just before each of the 4 recursive calls. What I dont get is, I end up with a segfault during the recursion at the recrusive call itself (I get the print that is just before the call, but not the one at function start).
void explore(Pixel * array, int j, Tache * cur_pound, int * it, Pixel previous){
printf("%d\n", j); // I DONT GET THIS PRINT AT LAST RECURSIVE CALL
// out of bounds
if(j > sizeX * sizeY)
return;
// allready explored index
if(array[j].explored == 1){
return;
}
// to big of a color difference between this pixel and the reference one
if(abs((int)array[j].r - previous.r) > SEUIL || abs((int)array[j].g - previous.g) > SEUIL || abs((int)array[j].b - previous.b) > SEUIL){
return;
}
array[j].explored = 1;
cur_pound->limits[* it] = j;
(* it)++;
// recursion
if(j +1 < sizeX * sizeY && array[j+1].explored != 1){
printf("before SF\n); // I GET THIS PRINTF
explore(array, j + 1, cur_pound, it, previous);
}
// 3 other recursive calls removed for simplicity here
}
About my data structures : a Tache * is struct that contains 3 GLubytes and limits, an int * that represents every pixel index that belongs to this group. A Pixel contains 3 GLubytes and a char that represents if this pixel has already been visited by the function. The array given to the function as the first argument is an array of Pixel that represent my image.
it is an int representing the index in the group so that my function knows where on the array it should add a new index.
Limits are initialised at -1 outside this function and are allocated with malloc(size * sizeof(int)) where size is the width of the image multiplied by its height.
This is how the inital call is done :
void taches_de_couleur(Image *i){
int j, k, y, size, it;
GLubyte * im;
Pixel * array;
sizeX = i->sizeX;
sizeY = i->sizeY;
k = 0;
size = sizeX * sizeY;
array = malloc(size * sizeof(Pixel));
im = i->data;
/* build the array from image data */
for(j = 0; j < 3 * size; j+= 3){
array[k].explored = 0;
array[k].r = i->data[j];
array[k].g = i->data[j + 1];
array[k].b = i->data[j + 2];
k++;
}
Tache * new_pound;
new_pound = malloc(sizeof(Tache));
new_pound->limits = malloc(size * sizeof(int));
int x= 0;
while(x < size){
new_pound->limits[x] = -1;
x++;
}
it = 0;
explore(array, 0, new_pound, &it, array[0]);
}
Note that the program does not produce any SF when working with small images (biggest i could do was 512x384px).
This thing has been giving me a headache for a week now, can't figure out what is causing this segfault and thats why im asking you guys if you can see anything obvious here. I can add the second function that calls explore if need be, but this part seems to be good.
EDIT : this is the output gdb gives me when I run it with a image too big :
Thread 1 "palette" received signal SIGSEGV, Segmentation fault.
0x00007ffff7b730be in __GI___libc_write (fd=1, buf=0x555555592770,
nbytes=7)
at ../sysdeps/unix/sysv/linux/write.c:26
26 ../sysdeps/unix/sysv/linux/write.c: No such file or directory.
EDIT : Since im failing to provide enough ressources, see https://github.com/BruhP8/TachesDeCouleur for the full project
Thanks in advance
What I dont get is, I end up with a segfault during the recursion at the recrusive call itself (I get the print that is just before the call, but not the one at function start).
That is an almost sure sign of stack exhaustion.
Run your program under debugger, and examine the instruction which causes segfault. Chances are, it will be one of stack manipulation instructions (CALL, PUSH), or a stack dereference instruction that follows stack decrement. You can also look at the value of $SP register, and compare it to the bounds of stack segment (from /proc/$pid/maps if you are on Linux).
The code you've shown does not appear to allocate any stack, so the problem is likely in the code you omitted.
Note that the program does not produce any SF when working with small images
That is another sign: you are probably allocating a new image on the stack, and the larger the image, the fewer levels of recursion you can achieve.
P.S. On Linux, default stack size is often 8MiB. Try ulimit -s unlimited -- if that allows the program to recur deeper, that would be a sure sign that my guess is correct. But don't use ulimit -s unlimited as a fix (it's not).
Update:
With the full source code, I was able to build the palette program. Each recursive call to explore only takes 48 bytes of stack (which isn't much).
But with default 8MiB stack, that limits the total recursion to (8 << 20) / 48 == 174762 levels deep.
TL;DR: if your recursive procedure requires one level of recursion per pixel, then you would not be able to process large images. You must rewrite the procedure to be iterative instead.
It seems the first boundary check in your code should be:
if( j >= sizeX * sizeY )
and not
if( j > sizeX * sizeY )
(As the last element of your array is array[size - 1] and not array[size])

Segmentation fault on copying string elements to another string

Why am I getting segmentation fault? I have listed my code below.
Please tell if anyone knows what is my fault here and how do I correct it?
What I am trying to do here
I am trying to take numbers as input and for them I have to output a string of characters.
Problem
link to the problem is here.
The code of my proposed solution
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
long long int n, k;
char manku[] = { 'm', 'a', 'n', 'k', 'u' };
char l[10000000];
int t, i = 0, j, p;
scanf("%d", &t);
while (t > 0)
{
scanf("%lld", &n);
while (n > 0)
{
j = n % 5;
if (j == 0)
l[i] = manku[4];
else
l[i] = manku[j - 1];
n = n / 5;
i++;
}
p = strlen(l);
for (i = 0; i < p; i++)
l[i] = l[p - 1 - i];
for (i = 0; i < p; i++)
printf("%c", l[i]);
t--;
}
return 0;
}
char l[10000000];
This huge array is overflowing your stack memory.
The stack memory segment is an area of memory allotted for automatic variables and its size is fairly small. It is not a good idea to have such a huge array in stack.
Try to allocate it dynamically, like this:
char *l;
l = malloc(10000000); //note: size of char is 1
With this, the memory allocated to l in heap segment. Make sure to free it once you done with it.
Alternatively, you can make l a global variable or a static local variable so that it will go in Data Segment.
You are getting a segmentation fault when you start running your binary because you are running out of stack memory due to the big size of your array char l[10000000] (you can check the size of your stack by running
$ ulimit -s
in your shell).
There are at least two solutions to this:
Increase the size of your stack. You can do this by running, e.g.,
$ ulimit -s unlimited
in your shell before running the binary.
Use malloc to allocate the l array, so that it is allocated in the heap rather than in the stack.
Firstly, initialize the variable i after scanning n.
while(t>0) {
scanf("%lld",&n);
i = 0; /* initialize i every time here */
while(n>0) {
/* some code */
}
}
Also instead of creating stack created array like char l[10000000]; create the dynamic array once before while loop and free the dynamically allocated memory once done. for e.g
char *l = malloc(SIZE); /* define the SIZE */
...
...
free(l);
Short Answer: The segmentation fault is caused by char l[10000000];. Decalring char l[26]; is sufficient.
Details
As others said the allocation char l[10000000]; causes the segmentation fault. You do not need this much memory. The question stated that the maximum value for n is 10^18. Thus the maximum length of a word would be 26 characters. Thus, char l[26]; is sufficient.
Explanation: It is given that you have 10^18 options to arrange k characters. Each charater has 5 options and thus the number of options to arrange these characters is 5^k. Now, you just have to find k:
5^k = 10^18 ==> k = log_5(10^18) ~= 25.75218 < 26
Implementation
Regarding the implementation, you have few wrong things going on.
You do not set i = 0; after each input scan.
Your can not use strlen without the terminating null-character. You should add l[i] = '\0'; above p = strlen(l);.
Your second for loop, the one that should revert the string, is not working properly. Each step changes the string and the steps after it use the changed string (instead of working with the original one).
Regarding the algorithm, it does not work properly as well. I can give you a hint: this problem is similar to counting in base-5.
Comments
The things above are just few things that I have noticed. I think you should consider rewriting the code since it may still contaion small flaws.
Another tip: for printing strings (character arrays in c) you can use
printf("%s", str);
Assuming that str is an array of character that ends with the terminating null-character. Some more information here.

int* vector accepts only the first given value

I'm experiencing some troubles with my code written in C. It's all about an int * vector intially declared and dynamically allocated but when it comes to filling it with data it stuck on the first element and won't increment the counter to fill the rest of the vector
my header file : instance.h
struct pbCoupe
{
int tailleBarre;
int nbTaillesDem;
int nbTotPcs;
int * taille;
int * nbDem;
};
my code : coupe.c
pb->taille = (int*) malloc (pb->nbTaillesDem * sizeof(int));
pb->nbDem = (int*) malloc (pb->nbTaillesDem * sizeof(int));
while (i < pb->nbTaillesDem)
{
fscanf_s(instanceFile,"%s",data,sizeof(data));
pb->taille[i] = atoi(data); //<-- here is the problem !! it only accept the first value and ignore all the rest
printf("%s\n",data);
fscanf_s(instanceFile,"%s",data,sizeof(data));
pb->nbDem[i] = atoi(data); //<-- the same problem here too !!
printf("%s\n",data);
i++;
}
Your interpretation of sizeof is wrong, since data is the buffer that the string is being parsed into.
It returns the size of the the variable, not the size of the the what the variable (or namely a pointer) points to
Strings in C are all pointer to the size would be 4 bytes on a 32-bit system, 8 on a 64-bit.
Since it prints all the number it reading more numbers that intended with each loop iteration 4 bytes = 4 characters, atoi on parses the first integer and returns,
EDIT: If it is a buffer array, sizeof returns the size of the array.
You need to make sure you are only reading in a single number per iteration of the loop to solve this issue.
If you don't care for the literal string, best thing you can do is use:
fscanf(instanceFile, "%d", ((pb->taille) + i)));
//and store the integer into the index right away
//last param same as &pb->taille[i]

Reallocing a char*

I am trying to do a function that will store in a char array some information to print on it:
int offset = 0;
size_t size = 1;
char *data = NULL;
data = malloc(sizeof(char));
void create(t_var *var){
size_t sizeLine = sizeof(char)*(strlen(var->nombre)+2)+sizeof(int);
size = size + sizeLine;
realloc(data, size);
sprintf(data+offset,"%s=%d\n",var->name,var->value);
offset=strlen(data);
}
list_iterate(aList, (void *)create);
t_var is a struct that has two fields: name (char*) and value (int).
What's wrong with this code? When running it on Valgrind it complains about the realloc and sprintf.
Without knowing the specific valgrind errors, the standout one is:
realloc(data, size); should be data = realloc(data, size);
I'm sorry to say that, but almost EVERYTHING is wrong with your code.
First, incomplete code.
You say your t_var type has two members, name and value.
But your code refers to a nombre member. Did you forget to mention it or did you forget to rename it when publishing the code?
Second, misused sizeof.
You use a sizeof(int) expression. Are you aware what you actually do here?!
Apparently you try to calculate the length of printed int value. Alas, operator sizeof retrieves the information about a number of bytes the argument occupies in memory. So, for example, for 32-bits integer the result of sizeof(int) is 4 (32 bits fit in 4 bytes), but the maximum signed 32-bit integer value is power(2,31)-1, that is 2147483647 in decimal. TEN digits, not four.
You can use (int)(2.41 * sizeof(any_unsigned_int_type)+1) to determine a number of characters you may need to print the value of any_unsigned_int_type. Add one for a preceding minus in a case of signed integer types.
The magic constant 2.41 is a decimal logarithm of 256 (rounded up at the 3-rd decimal digi), thus it scales the length in bytes to a length in decimal digits.
If you prefer to avoid floating-point operations you may use another approximation 29/12=2.41666..., and compute (sizeof(any_unsigned_int_type)*29/12+1).
Third, sizeof(char).
You multiply the result of strlen by sizeof(char).
Not an error, actually, but completely useless, as sizeof(char) equals 1 by definition.
Fourth, realloc.
As others already explained, you must store the return value:
data = realloc(data, size);
Otherwise you risk you loose your re-allocated data AND you continue writing at the previous location, which may result in overwriting (so destroying) some other data on the heap.
Fifth, offset.
You use that value to determine the position to sprintf() at. However, after the print you substitute offset with a length of last printout instead of incrementing it. As a result consecutive sprintfs will overwrite previous output!
Do:
offset += strlen(data);
Sixth: strlen of sprintf.
You needn't call strlen here at all, as all functions of printf family return the number of characters printed. You can just use that:
int outputlen = sprintf(data+offset, "%s=%d\n", var->name, var->value);
offset += outputlen;
Seventh: realloc. Seriously.
This is quite costly function. It may need to do internal malloc for a new size of data, copy your data into a new place and free the old block. Why do you force it? What impact will it have on your program if it needs to print five thousand strings some day...?
It is also quite dangerous. Really. Suppose you need to print 5,000 strings but there is room for 2,000 only. You will get a NULL pointer from realloc(). All the data printed to the point are still at the current data pointer, but what will you do next?
How can you tell list_iterate to stop iterating...?
How can you inform the routine above the list_iterate that the string is incomplete...?
There is no good answer. Luckily you needn't solve the problem — you can just avoid making it!
Solution.
Traverse your list first and calculate the size of buffer you need. Then allocate the buffer — just once! — and go on with filling it. There is just one place where the allocation may fail and you can simply not go into the problem if that ever happens:
int totaloutputlength = 0;
char *outputbuffer = NULL;
char *currentposition = NULL;
void add_var_length(t_var *var){
const int numberlength = sizeof(var->value)*29/12 + 1;
totaloutputlength += strlen(var->name) + 2 + numberlength;
}
void calculate_all_vars_length(t_list *aList){
totaloutputlength = 0;
list_iterate(aList, (void *)add_var_length);
}
void sprint_var_value(t_var *var){
int outputlen = sprintf(currentposition, "%s=%d\n", var->name, var->value);
currentposition += outputlen; // advance the printing position
}
int sprint_all_vars(t_list *aList){
calculate_all_vars_length(aList);
outputbuffer = malloc(totaloutputlength + 1); // +1 for terminating NUL char
// did allocation succeed?
if(outputbuffer == NULL) { // NO
// possibly print some error message...
// possibly terminate the program...
// or just return -1 to inform a caller something went wrong
return -1;
}
else { // YES
// set the initial printing position
currentposition = outputbuffer;
// go print all variables into the buffer
list_iterate(aList, (void *)sprint_var_value);
// return a 'success' status
return 0;
}
}

Resources