Program debugging using Valgrind - c

I am trying to solve a problem of "Multiplying a number by 11".Number can be any long.I am getting SIGABRT error.
I tried to debug using valgrind, but i don't know to solve it(saw many questions of valgrind on stackoverflow but no success).I am stuck on this problem since last week.
Code is :
#include <stdio.h>
#include <stdlib.h>
#define CHUNK 10
void get_input(char *val,int *i){
char ch,*tmp=NULL;
int size;
size=CHUNK;
while(ch=getc(stdin),ch!=EOF && ch!='\n'){
val[(*i)++]=ch;
if(*i>=size){
size+=CHUNK;
tmp=realloc(val,size);
if(!tmp){
free(val);
val=NULL;
break;
}
val=tmp;
}
}
val[*i]='\0';
}
void mul_11(char *val,int *i){
int *digit,iter,j,carry=0,num,temp;
iter=*i;
digit=(int*)malloc((iter+2)*sizeof(int));
for(j=iter-1;j>=0;j--){
temp=val[j]-'0';
num=temp*11+carry;
digit[j+2]=num%10;
carry=num/10;
}
digit[1]=carry%10;
digit[0]=carry/10;
if(digit[0]==0)
temp=1;
else
temp=0;
for(j=temp;j<=iter+1;j++)
printf("%d",digit[j]);
free(digit);
digit=NULL;
*i=0;
}
int main() {
int t,i=0;
char *val=NULL;
scanf("%d ",&t);
while(t--){
val=(char*)malloc(CHUNK*sizeof(char));
get_input(val,&i);
mul_11(val,&i);
printf("\n");
free(val);
val=NULL;
}
return 0;
}
Whole code with input can be found out Geeksforgeeks code here
Valgrind error :
5555555555555555555555555555555555555
==2349== Invalid read of size 1
==2349== at 0x4008CE: mul_11 (mul11.c:30)
==2349== by 0x400A8A: main (mul11.c:55)
==2349== Address 0x52044a4 is 20 bytes after a block of size 16 in arena "client"
==2349==
6111111105-3-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-6-60-8
==2349== Invalid free() / delete / delete[] / realloc()
==2349== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2349== by 0x400AA0: main (mul11.c:57)
==2349== Address 0x5204480 is 0 bytes inside a block of size 10 free'd
==2349== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2349== by 0x400809: get_input (mul11.c:13)
==2349== by 0x400A77: main (mul11.c:54)
==2349== Block was alloc'd at
==2349== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2349== by 0x400A60: main (mul11.c:53)
==2349==

If get_input reallocs your val and it gets a new address, the caller (main) will not be told that its value for val has become invalid (realloc has freed it). mul_11 will be using freed memory, and main will then free it for the second time.
One solution is to send in a pointer to the address, if the function can realloc it, so the caller gets the new values.
void get_input(char **valp,int *i){
char *val = *valp;
...
val = realloc ...
*valp = val;
...

Related

How to free an allocated memory without losing its value

Hello I wrote this function in C that takes a string of words and returns a two dimensional char array with each case initialized to a word in the right order, I compiled and it did the assigned task
char **decompose_string(char *string)
{
int i,j=0;
char* temp=malloc(sizeof(char*));
char **words_array=malloc((string_words_number(string)+1)*sizeof(char*)); //string_words_number return the number of words in string string
for(i=0;i<string_words_number(string);i++)
{
temp=NULL;
int l=0;
while(string[j]!=' ' && *string)
{
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]=string[j];
j++;l++;
}
j++;
temp[l]='\0';
tab_mots=realloc(words_array,(string_words_number(string)+1)*sizeof(char)*(j-1));
words_array[i]=temp;
}
words_array[i]=NULL;
return words_array;}
And my main:
int main()
{
char* string1= "word1 and word2 and word3";
printf("Our initial string: %s\n",string1);
char** words_array1;
printf("After decomposition:\n");
words_array1=decompose_string(string1);
display_words_array(words_array1); //displays each element of the array in a line
words_array1=destroy_array(words_array1);
return 0;}
But as I executed the valgrind command to see weither there are any memory leaks this was the result:
==4648== Memcheck, a memory error detector
==4648== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4648== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==4648== Command: ./test_csvl
==4648==
Our initial array: word1 and word2 and word3
After decomposition:
==4648== Invalid write of size 1
==4648== at 0x4009D9: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648== Address 0x5204634 is 0 bytes after a block of size 4 alloc'd
==4648== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x40097D: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648==
==4648== Invalid read of size 1
==4648== at 0x4C30F74: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x4EA969B: puts (ioputs.c:35)
==4648== by 0x400888: display_words_array (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40079F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648== Address 0x5204634 is 0 bytes after a block of size 4 alloc'd
==4648== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x40097D: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648==
word1
and
word2
and
word3
==4648==
==4648== HEAP SUMMARY:
==4648== in use at exit: 8 bytes in 1 blocks
==4648== total heap usage: 30 allocs, 29 frees, 1,545 bytes allocated
==4648==
==4648== LEAK SUMMARY:
==4648== definitely lost: 8 bytes in 1 blocks
==4648== indirectly lost: 0 bytes in 0 blocks
==4648== possibly lost: 0 bytes in 0 blocks
==4648== still reachable: 0 bytes in 0 blocks
==4648== suppressed: 0 bytes in 0 blocks
==4648== Rerun with --leak-check=full to see details of leaked memory
==4648==
==4648== For counts of detected and suppressed errors, rerun with: -v
==4648== ERROR SUMMARY: 9 errors from 2 contexts (suppressed: 0 from 0)
I know that the missing free is the one for temp in the function but if I do free it I'll end up losing its value which I need for my array. So my question would be can I free it without losing its value ? or any other solution to guarantee both the functionality of my function and the erase of any memory leaks. Thank you for your time.
Sorry I forgot here's the function I used to free the allocated space:
char **destroy_words_array( char** words_array)
{
int i;
for(i=0;i<count_words(words_array);i++) free(words_array[i]); //wount_words return the number of elements of the array
free(words_array);
return words_array;
}
The memory leak isn't where you think it is. It happens at the start of your function:
char* temp=malloc(sizeof(char*));
char **words_array=malloc((string_words_number(string)+1)*sizeof(char*));
for(i=0;i<string_words_number(string);i++)
{
temp=NULL;
You allocate space for a pointer to temp, but then you overwrite that pointer when you enter the for loop. Remove that malloc call and the leak goes away.
You have a bigger problem however, and that is reading and writing past the end of an allocated buffer. That's happening here:
temp=NULL;
int l=0;
while(string[j]!=' ' && *string)
{
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]=string[j];
j++;l++;
}
j++;
temp[l]='\0';
Suppose the string in question has two characters to read. On the first iteration of your loop, l is 0, so you allocate l+1 == 1 bytes to temp. You then write to temp[l] == temp[0], which is fine, then you increment l to 1. On the next iteration, you allocate l+1 == 2 bytes for temp, write to temp[l] == temp[1], and increment l to 2. Still good so far.
The problem is when you do temp[l]='\0'; outside of the loop. l is now 2, and the size of the allocated memory is 2, so you're writing one element past the end of the array.
You need to allocate one more byte here:
j++;
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]='\0';
Note also that you should be checking the return value of malloc and realloc throughout your code in case it fails.
Also, you're not correctly checking for the end of string. You need to do:
while(string[j]!=' ' && string[j]!=0)
Before the for-loop you have
char* temp=malloc(sizeof(char*));
but the first thing inside the for-loop is
temp=NULL;
So the memory that temp pointed to is lost. If you run this program on a 64 bit computer, you will see a memory leak of size 8. Remove the first declaration of temp and change the first line in the for-loop to
char* temp = NULL;
Another problem is the condition of the inner while-loop:
while(chaine[j]!=' ' && *chaine)
as you don't advance the chaine pointer, the value of *chaine will not change. You probably meant to write chaine[j] here:
while(chaine[j]!=' ' && chaine[j])
which is equivalent to
while(chaine[j]!=' ' && chaine[j]!='\0')

Using Dynamic Memory get every second element in a char array into another

I've been tasked with getting writing a function that uses dynamic memory and will take a string s and pull out every second element of the string, and then return a new string with those elements. So far my code is:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char* skipping(const char* s)
{
int inc = 0; //new list incrementer
int len = strlen(s);
char* new_s = malloc(len + 1);
for (int i = 0; i < len - 1; i+=2) {
new_s[inc] = s[i];
inc++;
}
return new_s;
}
int main(void)
{
char* s = skipping("0123456789");
printf("%s\n", s);
free(s);
return 0;
}
This works, however when I run it using Valgrind I get told I have an error, which comes from using strlen, but I can't seem to fix it. Any help would be awesome!
Error messages: (in valgrind)
==4596==
==4596== Conditional jump or move depends on uninitialised value(s)
==4596== at 0x4C32D08: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4596== by 0x4EBC9D1: puts (ioputs.c:35)
==4596== by 0x1087B4: main (in /home/ryan/ENCE260/lab6)
==4596==
02468 //this is the expected output
==4596==
==4596== HEAP SUMMARY:
==4596== in use at exit: 0 bytes in 0 blocks
==4596== total heap usage: 2 allocs, 2 frees, 1,035 bytes allocated
==4596==
==4596== All heap blocks were freed -- no leaks are possible
==4596==
==4596== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Why is Valgrind reporting this error?
From the Valgrind online manual on the use of uninitialised or unaddressable values in system calls:
Sources of uninitialised data tend to be:
- Local variables in procedures which have not been initialised.
- The contents of heap blocks (allocated with malloc, new, or a similar function) before you (or a constructor) write something there.
Valgrind will complain if:
the program has written uninitialised junk from the heap block to the standard output.
Since you have used s in printf without null-terminating it, it caused the error.

valgrind shows error for strtok with a large memory

I wrote a simple code that reads a very large file into memory. (The file is around 480 mega bytes in size). The file contains some comma separated values of 0s and 1s. The code is fairly straight forward. I first get the file size, then allocate enough buffer space, read the file, separate by comma and just put it in the array. The program is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
long no_of_houses = 1048576L; //dimensions of my final table.
int no_of_appliances = 5;
int no_of_sectors = 48;
int* intended_schedule; // this is where the table will be stored.
intended_schedule = (int*) malloc(no_of_houses * no_of_appliances * no_of_sectors * sizeof(int));
FILE* fptr = fopen("./data/houses.csv", "r"); //this file is around 480 mega bytes.
if(fptr == NULL){
perror("housese file");
exit(0);
}
fseek(fptr, 0L, SEEK_END); //find the size of the file before allocating space
long size = ftell(fptr);
rewind(fptr);
char* buffer = (char*) calloc(1, size); //now we know the size, we can allocate space.
fread(buffer, size, 1, fptr);
char* token = strtok(buffer, ",\n"); //it's a comma separated file. So break from comma
long no = 0;
while(token != NULL){
if(no == no_of_houses*no_of_appliances*no_of_sectors)
break; //guard against unexpectedly big data file.
intended_schedule[no] = token[0] - 48;// it's either 0 or 1. So this is good enough
no++;
token = strtok(NULL, ",\n");
}
fclose(fptr);
free(intended_schedule);
free(buffer);
return 0;
}
I used this code as a function of a bigger program and since it gave me errors, I ran this program through valgrind. This is the result I got:
goodman#node2 analyse_code]$ valgrind ./analyse
==39263== Memcheck, a memory error detector
==39263== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==39263== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==39263== Command: ./analyse
==39263==
==39263== Warning: set address range perms: large range [0x51f8040, 0x411f8040) (undefined)
==39263== Warning: set address range perms: large range [0x59e3f040, 0x77e3f040) (defined)
==39263== Warning: set address range perms: large range [0x59e3f040, 0x77e3f040) (defined)
==39263== Invalid read of size 1
==39263== at 0x4EBEDCC: strtok (in /usr/lib64/libc-2.17.so)
==39263== by 0x400997: main (analyse.c:36)
==39263== Address 0x77e3f040 is 0 bytes after a block of size 503,316,480 alloc'd
==39263== at 0x4C2B9B5: calloc (vg_replace_malloc.c:711)
==39263== by 0x400904: main (analyse.c:27)
==39263==
==39263== Invalid read of size 1
==39263== at 0x4EBEDFC: strtok (in /usr/lib64/libc-2.17.so)
==39263== by 0x400997: main (analyse.c:36)
==39263== Address 0x77e3f040 is 0 bytes after a block of size 503,316,480 alloc'd
==39263== at 0x4C2B9B5: calloc (vg_replace_malloc.c:711)
==39263== by 0x400904: main (analyse.c:27)
==39263==
==39263== Warning: set address range perms: large range [0x51f8028, 0x411f8058) (noaccess)
==39263== Warning: set address range perms: large range [0x59e3f028, 0x77e3f058) (noaccess)
==39263==
==39263== HEAP SUMMARY:
==39263== in use at exit: 0 bytes in 0 blocks
==39263== total heap usage: 3 allocs, 3 frees, 1,509,950,008 bytes allocated
==39263==
==39263== All heap blocks were freed -- no leaks are possible
==39263==
==39263== For counts of detected and suppressed errors, rerun with: -v
==39263== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
I'm wondering why I get these errors. As far as I can tell, there are no problems with my code. Is it because my data is too large? I don't think that could be the case since I run this code on a server with 128 GB of RAM.
Any help would be appreciated.
--ppgoodman
strtok() assumes a NUL-terminated string, your buffer is NOT NUL-terminated, so strtok() will try to walk beyond the end of your buffer. But you can do withoutstrtok() and the large buffer.
You don't need to buffer the entire file; for simple cases like this, you can step through it using a one-character buffer. This will consume less memory and will also be consirably faster (at least 2 times)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
unsigned long no_of_houses = 1048576L; //dimensions of my final table.
unsigned int no_of_appliances = 5;
unsigned int no_of_sectors = 48;
unsigned long no = 0;
int ch;
unsigned int *intended_schedule; // this is where the table will be stored.
intended_schedule = malloc(no_of_houses * no_of_appliances * no_of_sectors * sizeof *intended_schedule);
FILE *fptr = fopen("./data/houses.csv", "r"); //this file is around 480 mega bytes.
if(!fptr) {
perror("housese file");
exit(0);
}
while(no < no_of_houses*no_of_appliances*no_of_sectors) {
ch = getc(fptr);
if (ch== EOF) break;
if (ch== '\n') continue;
if (ch== ',') continue;
intended_schedule[no++] = ch - '0'; // it's either 0 or 1. So this is good enough
}
fclose(fptr);
free(intended_schedule);
return 0;
}

C token loop segfault issue

So sort of new to C and I am trying to make a listener so that User has to press enter twice to completed typing there input. Then split by the new line and run all the data through a loop and send them through my functions.
I am not sure what i am doing wrong but when the loop right under "//segfaulting at loop" in the code is commented out it runs fine but when I uncomment it and have my call to "// assemble(ftemp);" commented it out it is segfaulting so i know it here just dont know what. Valgrind says the below if that helps at all.
Thanks In Advanced Pete.
==14639== Invalid read of size 1
==14639== at 0x4E7754C: ____strtod_l_internal (strtod_l.c:608)
==14639== by 0x4011F8: main (in /home)
==14639== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14639== Process terminating with default action of signal 11 (SIGSEGV)
==14639== Access not within mapped region at address 0x0
==14639== at 0x4E7754C: ____strtod_l_internal (strtod_l.c:608)
==14639== by 0x4011F8: main (in /home)
==14639== If you believe this happened as a result of a stack
==14639== overflow in your program's main thread (unlikely but
==14639== possible), you can try to increase the size of the
==14639== main thread stack using the --main-stacksize= flag.
==14639== The main thread stack size used in this run was 8388608.
==14639== HEAP SUMMARY:
==14639== in use at exit: 0 bytes in 0 blocks
==14639== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==14639== All heap blocks were freed -- no leaks are possible
==14639== For counts of detected and suppressed errors, rerun with: -v
==14639== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
My code:
int main(int argc, char * argv[]) {
printf("Please Enter In Float (Hit Enter Twice To Exicute)\n" );
#define MAXLENGTH 1000
char Input_string[MAXLENGTH];
int ilop = 0;
for(;;++ilop)
{
Input_string[ilop] = getchar();
if (ilop > 0 && Input_string[ilop] == '\n' &&
Input_string[ilop-1] == '\n') break;
}
Input_string[ilop] = 0;
char *pch;
// printf ("Splitting string \"%s\" into tokens:\n",Input_string);
pch = strtok (Input_string,"\n");
float ftemp = atof(pch);
//printf("price:, %f\n\n",ftemp);
assemble(ftemp);
//segfaulting at loop
while (pch != NULL)
{
pch = strtok (NULL, "\n");
ftemp = atof(pch);
printf("price:, %f\n\n",ftemp);
// assemble(ftemp);
}
return 0;
}
To expand on what Igal S. said, you’re first setting strtok inside the loop, then using it, and not checking it until the top of the loop. So, on the last iteration, it will set pch to NULL, then pass it to atof() without checking it.
You need something like (untested):
pch = strtok (Input_string, "\n");
while (pch != NULL)
{
/* ... */
pch = strtok (NULL, "\n");
}
There is a possibility of array out of bound access which might lead to undefined behavior.
In the for loop at the beginning add the check
if(ilop > 999)
{
break;
}

Invalid Write with strcpy

I have been programming for a while but I am new to C. I have this linked list implementation in ansi C that I need to test. I have narrowed the problem down to an issue with an invalid write. I ran the code through Valgrind and received the following output:
==18131== Invalid write of size 1
==18131== at 0x4C2C0CC: __GI_strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64 linux.so)
==18131== by 0x40089B: main (in /home/btm7984/hw3/TestList)
==18131== Address 0x51f1388 is 0 bytes after a block of size 8 alloc'd
==18131== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18131== by 0x400880: main (in /home/btm7984/hw3/TestList)
==18131==
==18131== Invalid write of size 1
==18131== at 0x4C2C0DF: __GI_strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18131== by 0x40089B: main (in /home/btm7984/hw3/TestList)
==18131== Address 0x51f138e is 6 bytes after a block of size 8 alloc'd
==18131== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18131== by 0x400880: main (in /home/btm7984/hw3/TestList)
==18131==
--18131-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--18131-- si_code=1; Faulting address: 0x6D4FCAA; sp: 0x402bdae00
All that I can ascertain from this is that I am allocating something wrong. I think it has to be with my strcpy line. I really don't know how to approach this question. What follows is my use of the LinkedLists interface. InitLinkedLists, AddToBackOfList, and DestroyList are all defined in that interface.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "LinkedLists.h"
int main(int argc, char *argv[]) {
FILE *fp;
char tmpString[100];
LinkedLists *ListPtr = malloc(sizeof(LinkedLists));
ElementStructs *DataPtr;
LinkedListNodes* curr = malloc(sizeof(LinkedListNodes));
int counter = 0;
int Done = 0;
InitLinkedList(ListPtr);
fp = fopen(argv[1], "r");
if (!fp){
fprintf(stderr,"%s Cannot open file %s\n", argv[0], argv[1]);
exit(1);
}
do{
fscanf(fp,"%s",tmpString);
if (!feof(fp)) {
DataPtr = malloc(sizeof(DataPtr));
printf("%d %d : %d\n",counter,(int)strlen(DataPtr->str),(int)strlen(tmpString));
strcpy(DataPtr->str,tmpString);
DataPtr->index=counter;
AddToBackOfLinkedList(ListPtr, DataPtr);
counter++;
Done = 1;
} else {
Done = 0;
}
}while (Done);
In conclusion, I think strcpy is causing an invalid write and I don't know why.
Any help would be greatly appreciated. Thanks in advance.
EDIT: ElementStructs is defined as follows:
typedef struct ElementStructs
{
/* Application Specific Definitions */
int index;
char str[100];
} ElementStructs;
The problem resides in this statement:
DataPtr = malloc(sizeof(DataPtr));
You allocate only enough memory to hold a pointer and not a full struct.
You should allocate using:
DatapPtr = malloc(sizeof(ElementStructs));
or, as described in the comments (WhozCraig):
DatapPtr = malloc(sizeof(*DataPtr));

Resources