Invalid read - Valgrind and C - c

New to C and Valgrind and manual memory management and I'm having trouble locating an error that I'm getting when I run Valgrind. I have this function which gets strings from the user:
char **get_fragments_from_user(){
// No more than 20k strings containing at most 1k characters
char **strings = malloc(20000 * sizeof(char *));
char tempstring[MAX_INPUT]; //MAX_INPUT = 1001
int count = 0;
while(true){
printf("\n> ");
fgets(tempstring, MAX_INPUT, stdin);
if((strlen(tempstring) > 0) && (tempstring[strlen(tempstring) - 1] == '\n')){
tempstring[strlen(tempstring) - 1] = '\0';
}
if(tempstring[0] == 'q') break;
strings[count] = malloc(sizeof(char) * (strlen(tempstring)+1));
strcpy(strings[count], tempstring);
count++;
}
int i = 0;
char **fstrings = malloc((count)*sizeof(char *)); // count+1 needed? Something I tried removing while debugging
for(i = 0; i < count; i++){
fstrings[i] = malloc(sizeof(char) * (strlen(strings[i])+1));
strcpy(fstrings[i], strings[i]);
free(strings[i]);
}
free(strings);
return fstrings;
}
The idea here is simply to get strings and put them in an array. I initially allocate an array that is large enough to fit the maximum number of strings that could ever be entered (20,000), but I then resize the array so that I don't allocate more memory than the each string needs. I am a little embarrassed with the above code, since its less clean than anything I would have written in another language, but that was my first pass through.
I then get "Invalid read of size 8" from Valgrind when I try to calculate the number of strings in the array using this function:
int lengthOf(char **arr){
int i = 0;
while(arr[i] != NULL){
i++;
}
return i;
}
I'm pretty sure this is due to a dereferenced pointer or something, but I can't find it for the life of me and I've been looking at this code for an hour or so.

So, I believe the problem was that I wasn't allocating enough memory to store the whole array.
Instead of doing:
malloc(count * sizeof(char *));
I should have been allocating count+1, so either:
malloc((count + 1) * sizeof(char *))
or
calloc((count + 1), sizeof(char *));

Related

How to read a file text array item by item using realloc() function?

I have a text file with an array of integers. I need to read item by item regardless of the number of rows and columns to a dynamic array. It seems that the realloc() function do what I want. How to use it to add one item at a time ?
I'm lost in this piece of code:
i = 0;
while (fgets(temp, sizeof(tempMatriz), Matriz) != NULL)
{
token = strtok(temp, " ");
j = 0;
// **FIRST LINE OF DYNAMIC ARRAY**
MatrizTemp = (int **) realloc (MatrizTemp, sizeof(int) * (i + 1));
while(token != NULL)
{
**FIRST COLUMN OF DYNAMIC ARRAY**
MatrizTemp[i] = (int *) realloc (MatrizTemp, sizeof(int)));
MatrizTemp[i][j] = atoi(token);
token = strtok(NULL, " ");
j++;
}
i++;
}
Thanks for any help.
MatrizTemp = (int **) realloc (MatrizTemp, sizeof(int) * (i + 1)); seems you expect an int** so your size could be wrong - should be sizeof(int*) * num_reqd
MatrizTemp[i] = (int *) realloc (MatrizTemp, sizeof(int))); is always reallocating one int - needs to be tied up with the value of j.
having said all of that: This is not a very efficient way to do it. Ok for a learning exercise, but production code? No.

Dynamic array using malloc and realloc?

I'm trying to collect input integers one by one. My array starts with size 1 and I want to expand it by 1, with every input collected (is this a smart thing to do?)
Anyway, this is the code I managed to come up with, but it's not working as intended.
After this process, sizeof(array) always returns 8, which I assume means that the array is only being resized once. (sizeof(int) is 4 bits)
Trying to output the array results in multiple instances of the first input variable.
OUTPUT CODE
for(int s=0;s<sizeof(array)/sizeof(int);s++){
printf("%i\n",array[i]);
}
ORIGINAL CODE:
int i;
int size = 1;
int *array = malloc(size * sizeof(int));
int position = 0;
do{
i = getchar() - 48;
f (i != -16 && i != -38 && i != 0) {
array[position] = i;
position++;
size++;
*array = realloc(array, size * sizeof(int));
}
} while (i != 0);
UPDATED STILL NOT WORKING CODE
int i;
int size = 1;
int *array = malloc(size * sizeof(int));
int position = 0;
do{
i = getchar() - 48;
f (i != -16 && i != -38 && i != 0) {
array[position] = i;
position++;
size++;
array = realloc(array, size * sizeof(int));
}
} while (i != 0);
array = realloc(...)
not *array. Per the realloc docs, realloc returns the pointer, which you can store directly in your array pointer.
Edit One thing that will make your life easier: use char constants instead of raw numbers. E.g.,
i = getchar();
if(i != ' ' && i != '\n' && i != '0') {
/* 48-16 48-38 48-0 right? */
array[position] = i - '0'; /* '0' = 48 */
One thing that jumps out at me: inside your loop, this line:
*array = realloc(array, size * sizeof(int));
should instead be:
array = realloc(array, size * sizeof(int));
In the original version, you were sticking the result of realloc in the first element of the array by dereferencing the pointer first. Without the asterisk, you're reassigning the array itself.
(With some copy-paste from my comment:) sizeof(array) returns 8 because it equals sizeof(int*) (array is type int*) which is 8 (you're probably compiling as 64-bit). sizeof doesn't work how you think for pointers to arrays.
Similarly, your output code is wrong, for the same reason. You only print the first two elements because sizeof(array)/sizeof(int) will always be 8/4=2. It should be
for(int s=0;s<size;s++){
printf("%i\n",array[s]);
}
(note also changed index variable i to s)
where size is the variable from your other code chunk(s). You cannot find the length of the array from sizeof if it's dynamically allocated with pointers; that's impossible. Your code must "remember" the size of your array.

how to use a 2D array in C

I am new in C and I am trying to create a 2D array of chars.
The logic behind this is to get unknown amount of string inputs
from the user and to be able to get to those strings
(each string ends with a ":") but when I tried to debug I got:
<Error reading characters of string>
This is the code:
int main()
{
int j = 0, rows = 50;
int i=0, lines = 50;
char **names;
names = (char**)malloc(lines*sizeof(char*));
if (i >= lines)
{
names = (char**)realloc(names, 10 * sizeof(char*));
lines = lines * 10;
}
for (j ; names[i][j] != ':'; j++)
{
*names = (char*)malloc(rows * sizeof(char));
if (j >= rows)
{
*names = (char*)realloc(names, 10 * sizeof(char));
rows = rows * 10;
}
scanf("%c", &names[i][j]);
}
i++;
return 0;
}
for (j ; names[i][j] != ':'; j++)
In this loop your test condition tests for ':' in names . names has been allocated memory but it does not contain any content (what will it compare to ?).
Use a do-while loop , in order to execute loop before reading characters in names.
Also you allocate memory for char *'s but you don't allocate memory to these pointers correctly . And without allocating memory correctly you try to store characters at location they point to . This will cause problem .
Allocate memory to each char * and then take input .
Some this like this can be done -
do{
names[i] =malloc(rows * sizeof(char));
if(names!=NULL){
if (j >= rows)
{
*names = (char*)realloc(names, 10 * sizeof(char));
rows = rows * 10;
}
scanf("%c", &names[i][j]);
j++;
i++;
}
}while(names[i][j]!=':')'
Note-
1. You should free the allocated memory . And you first if will not execute (can't understand its use ).
2. Check return of malloc.

Allocate a 3D char array in C (char ***)

I would like to allocate a char***.
I have a got a sentence like this: "This is a command && which I || need to ; split"
I need to put in each box a full sentence just like that:
cmd[0] = "This is a command"
cmd[1] = "wich I"
cmd[2] = "need to"
cmd[3] = "split"
Sentences are separated by tokens like &&, ||, ;, |.
My problem is that I don't know how to allocate my triple dimension array.
I always get a Segmentation Fault.
This is what I do :
for(k = 0; k < 1024; k++)
for( j = 0; j < 1024; j++)
cmd[k][j] = malloc(1024);
But a few line later, in an other loop :
ยป cmd[k][l] = array[i];
I get a segfault here.
How can I do this please ?
Thanks in advance
Please keep in mind that a 2/3D array in C is not the same as a char ***.
If all you wish is to have a 1024^3 character array then you will be good with
char array[1024][1024][1024];
But keep in mind that this will allocate 1 GB of space on your stack which may or may not work.
To allocate this much on the heap you need to type it correctly:
char (*array)[1024][1024] = malloc(1024*1024*1024);
In this scenario array is a pointer to an array of 2D 1024x1024 character matrices.
If you really want to work with char *** (which I do not recommend if your array lengths are static) then you need to allocate all intermediary arrays too:
char *** cmd = malloc(sizeof(char **) * 1024);
for(k = 0; k < 1024; k++) {
cmd[k] = malloc(sizeof(char *) * 1024);
for( j = 0; j < 1024; j++)
cmd[k][j] = malloc(1024);
}
If you are going to be splitting your string by delimiters that are longer then a single character then this is how you could do it with string search.
The following function will accept an input string and a delimiter string.
It will return a char ** which has to be freed and it will destroy your input string (reusing it's memory to store the tokens).
char ** split_string(char * input, const char * delim) {
size_t num_tokens = 0;
size_t token_memory = 16; // initialize memory initially for 16 tokens
char ** tokens = malloc(token_memory * sizeof(char *));
char * found;
while ((found = strstr(input, delim))) { // while a delimiter is found
if (input != found) { // if the strind does not start with a delimiter
if (num_tokens == token_memory) { // increase the memory array if it is too small
void * tmp = realloc(tokens, (token_memory *= 2) * sizeof(char *));
if (!tmp) {
perror("realloc"); // out of memory
}
tokens = tmp;
}
tokens[num_tokens++] = input;
*found = '\0';
}
// trim off the processed part of the string
input = found + strlen(delim);
}
void * tmp = realloc(tokens, (num_tokens +1) * sizeof(char *));
if (!tmp) {
perror("realloc"); // something weird happened
}
tokens = tmp;
// this is so that you can count the amount of tokens you got back
tokens[num_tokens] = NULL;
return tokens;
}
You will need to recursively run this to split by more then one delimiter.

Reallocate a 2d char array

I have following code
int wordLenght = 256, arrayLength = 2, i = 0, counter = 0;
char **stringArray = NULL;
stringArray = calloc(arrayLength, sizeof(*stringArray));
for(counter; counter<wordLenght; counter++)
stringArray[counter] = calloc(wordLenght, sizeof(stringArray));
while(1)
{
printf("Input: ");
fgets(stringArray[i], wordLenght, stdin);
printf("stringArray[%d]: %s\n", i, stringArray[i]);
if(i == arrayLength)
{
printf("Reallocation !!!\n");
arrayLength *= 2;
stringArray = realloc(stringArray, arrayLength*sizeof(*stringArray));
}
i++;
}
I get this reallocation error:
*** glibc detected *** ./stringArray: realloc(): invalid next size: 0x0000000000b49010 ***
======= Backtrace: =========
/lib/libc.so.6(+0x775b6)[0x7f4dd12565b6]
/lib/libc.so.6(+0x7dd66)[0x7f4dd125cd66]
/lib/libc.so.6(realloc+0xf0)[0x7f4dd125d080]
./stringArray[0x4007f9]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f4dd11fdc4d]
./stringArray[0x400629]
What's my problem here ???
Thanks, greets
stringArray = calloc(arrayLength, sizeof(*stringArray));
Here you probably wanted to use sizeof(char*)
for(counter; counter<wordLenght; counter++) stringArray[counter] = calloc(wordLenght, sizeof(stringArray));
Here you are looping 256 times (wordLenght) but you should only 2 times (arrayLength). Additionally you probably wanted to use sizeof(char) instead of sizeof(stringArray).
if(i == arrayLength) {...}
This check should be done before you call fgets, because right now you are firstly using memory and later allocate them.
Additionally after you reallocate stringArray you need to allocate rest of strings using something like this
for(counter = i; counter<arrayLength; counter++) stringArray[counter] = (char*)calloc(wordLenght, sizeof(char));
And finally you need to free all allocated memory before you exit application.
You probably didn't mean sizeof(*stringArray)
In fact I believe you may want to relook at the calloc call too, I think you are allocating the size of the pointer there (word length times).
After the first time this line executes:
stringArray = realloc(stringArray, arrayLength*sizeof(*stringArray));
then stringArray[arrayLength/2] will be a garbage value - you haven't set it to point to storage for the word.
This part should use either use sizeof(**stringArray), or 1 as **stringArray is char, and the counter should only go up to arrayLength:
for(counter; counter<wordLenght; counter++)
stringArray[counter] = calloc(wordLenght, sizeof(stringArray));
Instead allocate in one block:
char* block = malloc(wordLength * arrayLength);
for ( counter; counter < arrayLength; ++counter )
stringArray[counter] = block + ( counter * wordLength );
At the moment, it's possible that there is some space after stringArray, into which you are storing the (wordLength-arrayLength) extra pointers when you calloc them, and realloc doesn't move stringArray.
It's quite probable that 0xb49010 is one of the pointers you calloc'd, and you're overwritten the memory where malloc keeps its block size..
But since you're writing off the end of stringArray, you're into undefined behaviour anyway.
Ok here is the whole solution:
int wordLength = 256, arrayLength = 2, i = 0, counter = 0;
char **stringArray = NULL;
char buffer[wordLength];
stringArray = calloc(arrayLength, sizeof(char*));
for(counter; counter<arrayLength; counter++) stringArray[counter] = (char*)calloc(wordLength, sizeof(char));
while(1)
{
if(i == arrayLength)
{
printf("Reallocation !!!\n");
arrayLength *= 2;
stringArray = realloc(stringArray, arrayLength*sizeof(char*));
for(counter = i; counter<arrayLength; counter++) stringArray[counter] = (char*)calloc(wordLength, sizeof(char));
}
printf("Input: ");
fgets(buffer, wordLength, stdin);
if(!strcmp(buffer,"q\n")) break; // also free here
else stringArray[i] = buffer;
printf("stringArray[%d]: %s\n", i, stringArray[i]);
i++;
}
How is the best way to free the space ?!

Resources