I want to fix problem reported by valgrind:
==7182== Conditional jump or move depends on uninitialised value(s)
==7182== at 0x40EC75C: strstr (in /lib/libc-2.9.so)
==7182== by 0x804A977: search_graph_begin (compression.c:462)
==7182== by 0x804AB60: search_graph_end (compression.c:497)
==7182== by 0x804AA97: search_graph_begin (compression.c:477)
==7182== by 0x804B59A: do_g_decompress (compression.c:767)
==7182== by 0x804996C: main (server.c:302)
my relevant part of code is:
void search_graph_begin(char* buf, FILE *dest,int* graph_count,int extension,
char* graphs,char* directory,int have)
{
char* begingraph = NULL;
begingraph = strstr(buf,"<GRAPH>");
if (begingraph != NULL)
{
if ( (int)(begingraph - buf) > 1)
{
printf("(int)(begingraph-buf) %d\n",(int)(begingraph-buf));
xwrite(dest,buf,(int)(begingraph-buf));
}
(*graph_count)++;
sprintf(graphs,"%s/tmp/graphs%d/graph%d",directory,extension,(*graph_count));
/*open file to save received graph data*/
FILE* graphfile = fopen(graphs,"wb");
if (graphfile == NULL)
fprintf(stderr,"could not create graph file\n");
search_graph_end(begingraph+strlen("<GRAPH>")+1,graphfile,dest,graph_count,extension,graphs,directory,
have-(begingraph+strlen("<GRAPH>")+1-buf));
}
else
{
if (have > 1)
xwrite(dest,buf,have);
buf = NULL;
}
}
void search_graph_end(char* buf, FILE* graphfile, FILE *dest,int* graph_count,int extension,
char* graphs,char* directory,int have)
{
char* endgraph = NULL;
endgraph = strstr(buf,"<GRAPH/>");
if (endgraph != NULL)
{
xwrite(graphfile,buf,sizeof(char)*(endgraph-buf));
fclose(graphfile);
search_graph_begin(endgraph+strlen("<GRAPH/>")+1,dest,graph_count,extension,graphs,directory,
have-(endgraph+strlen("<GRAPH/>")+1-buf));
}
else
{
if (have > 1)
xwrite(graphfile,buf,have);
buf = NULL;
}
}
the program runs fine under valgrind but its not the case when not. The idea of the program is to read in loop a buffer and write text between valise and in different files
A program that crashes in one environment, but not in a slightly different environment (under Valgrind, in gdb, different -O) is a telltale sign of undefined behaviour caused by a bug. The thing is though that the actual bug (eg. an off-by-one write) can be located anywhere in your program. The stack trace only tells you where the bug was detected. You need to look beyond the stack trace to find the actual bug. What part of your program is responsible for initializing the value that Valgrind complains about?
Related
I'm currently using Clion 2017.3.4 in C99.
while trying to run and debug my program, the debugger jumps into 'disassembly view', and I want to know what the problem is.
basically, the function gets a season(type), a input string (season_info), and an index, that points to a different place in the input string.
the function should return the year as an integer, while the input is a string
the disassembly view is showen when I step into the free() line.
any ideas what the problem is?
and generally what the disassembly view means?
int GetSeasonYear(Season season, const char* season_info, int *index){
char* tmp_str = GetStringByLine(season_info, index);
if(tmp_str == NULL){
SeasonDestroy(season);
return 0;
}
season->season_year = atoi(tmp_str);
free(tmp_str);
return 1;
}
this is the function used inside the GetSeasonYear function(although I check and it works fine).
char* GetStringByLine(const char* season_info, int* index){ // change back to static
int i = 0;
while(season_info[i] != '\n'){
i++;
}
char* tmp_str = malloc(sizeof(char)*(i+1));
if(tmp_str == NULL){
return NULL;
}
memcpy(tmp_str, season_info, sizeof(char)*i);
tmp_str[i+1]='\0';
*index = i;
return tmp_str;
}
thanks
You are stepping into a function (free) for which you either
a) Do not have the source for
or
b) have the source for but the debuuger cannot locate it.
free() is a call to the system to release memory. It's more than likely been compiled with high optimisation and without debug symbols, so the best the debugger can do is just show you the disassembled machine code that it's executing.
Basically, it's normal. There's also very little benefit to stepping into calls like that.
Code snippet follows.
Background: Revising a old C windows application to communicate with new instruments (while maintaining as much old code as possible), which requires the addition of new features. In this case I am copying file names from a directory into a 2D array to populate a list of the file names.
While debugging, the program gets to the realloc call (the second realloc, as the first is skipped by the if statement) and then breaks with the error which precedes the code snippet below.
At the time of realloc, WFMLIST has been allocated, with the first element initialized to 0, and NbItemWFMLIST = 1. So my question is, does anybody know why this error might be occurring? The memory allocation and reallocation worked before I added the directory searching and copying components. Is it DLL releated? I have tried many things (suggestions from similar errors on Stackoverflow), including replacing the realloc with a free() and then calloc() and received the same error.
Also, ffd is correctly finding the directory and providing the appropriate string in ffd.cFileName.
Please let me know if I can provide more information. Thanks.
HEAP[vhf.exe]: Heap block at 01068980 modified at 01068989 past
requested size of 1 Windows has triggered a breakpoint in vhf.exe.
This may be due to a corruption of the heap, which indicates a bug in
vhf.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while vhf.exe has focus.
char **WMFLIST=NULL;
long int NbItemWFMLIST = 0;
unsigned int playback_bytes;
WIN32_FIND_DATA ffd; //Added for directory search
LARGE_INTEGER filesize; //
TCHAR szDir[MAX_PATH]; //
TCHAR *pwrkDir;
size_t length_pwrkDir;
HANDLE hFind = INVALID_HANDLE_VALUE;
pwrkDir = (TCHAR *)calloc(5, sizeof(TCHAR));
if(WFMLIST==NULL)
{
WFMLIST=(char **)calloc(NbItemWFMLIST,sizeof(char *));
if(WFMLIST != NULL)
{
WFMLIST[0]=(char *)calloc(13,sizeof(char));
if(WFMLIST[0]==NULL)
{
MessageBox(hWnd,"CALLOC WMLIST[0]==NULL","Memory allocation error",MB_OK);
NbItemWFMLIST=0;
return(0); **error check
}
else
{
NbItemWFMLIST=1;
sprintf_s(&WFMLIST[NbItemWFMLIST-1][0],MAX_PATH,"\0");
}
}
else
{
**error
}
}
else
{
WFMLIST = (char **)realloc((void *) WFMLIST,sizeof(char *));
if(WFMLIST==NULL)
{
**error check
}
else
{
NbItemWFMLIST=1;
sprintf(&WFMLIST[NbItemWFMLIST-1][0],"\0");
}
}
if((tawg->status = GetCurrentDirectory(MAX_PATH,pwrkDir))==SIG_SUCCESS) //Locate the current working directory
{
**Error check
}
sprintf_s(pwrkDir, MAX_PATH, "%s\\Waveforms", pwrkDir); //Append directory with Waveform folder
strcpy(szDir, pwrkDir);
strcat(szDir,"\\*");
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind)
{
**error check
}
while (FindNextFile(hFind, &ffd) != 0);
{
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
**error check
}
else
{
WFMLIST=(char **)realloc((void*)WFMLIST,((NbItemWFMLIST+1)*sizeof(char *)));
if (WFMLIST[NbItemWFMLIST]==NULL)
{
**error
}
else
{
WFMLIST[NbItemWFMLIST]=(char *)calloc(13,sizeof(char));
if (WFMLIST[NbItemWFMLIST]==NULL)
{
**error
}
else
{
sprintf(&WFMLIST[NbItemWFMLIST][0],"%s",ffd.cFileName);
NbItemWFMLIST=NbItemWFMLIST+1;
}
}
}
}
I am creating a program in c which is based on a linked list, where every node (of struct) holds an integer and a pointer to the next node.
I use dynamic allocation (malloc) and deallocation (free) as new nodes are added and old nodes are deleted.
when a node is deleted a function named delete is called.
I discovered that the program crashes sometimes when this delete-function is called and I KNOW that its something with the pointers in the method but I dont know WHERE in the code (row number) and WHY this happends.
I am used to high-level languages such as Java and I am used to encircle the problem by putting print-syntax at certain places in the method just to reveal WHERE it crashes.
I thought I could do the same with c and with pointer because to my knowledge I beleive the code is read from top to bottom that is 1, 2, 3, 4, and so on. (maybe interrupt handlers behave another way?)
So in this function named delete I have gone so far by putting this printf() at the very beginning of the delete-function - and all the same the program crashes.
So my Question - is it really possible that its some syntax in the delete-function (when I loop pointers for instance) that causes the crash WHEN not even the printf() is printing?
Am I wrong when I believe that the program is executed from to to bottom - that is 1, 2, 3 ....
You can se my printf-function in the very beginning of delete-function
And by the way - how could I solve this problem when I get this cryptic crash message from windows? See the bitmap!!
Greatful for answers!!!
int delete(int data) {
printf("IN THE BEGINNING OF DELETE!!!");
int result = 0;
if (queueref.last != NULL) {
node *curr_ptr;
node *prev_ptr;
node *temp_ptr;
if (queueref.first->data == data) {
temp_ptr = queueref.first;
queueref.first = queueref.first->next;
destroy_node(temp_ptr);
result = 1;
if (queueref.first == NULL) {
queueref.last = NULL;
puts("queue is now empty!!!");
}
} else {
prev_ptr = queueref.first;
curr_ptr = queueref.first->next;
printf("prev_ptr: %d\n", prev_ptr);
printf("curr_ptr: %d\n", curr_ptr);
while(curr_ptr != NULL) {
if (curr_ptr->data == data) {
result = 1;
if (curr_ptr->next != NULL) {
temp_ptr = curr_ptr;
destroy_node(temp_ptr);
prev_ptr->next = curr_ptr->next;
} else {
temp_ptr = curr_ptr;
queueref.last = prev_ptr;
prev_ptr->next = NULL;
destroy_node(temp_ptr);
}
}
curr_ptr = curr_ptr->next;
prev_ptr = prev_ptr->next;
}
}
}
return result;
}
Common mistake, here's the deal. This
printf("IN THE BEGINNING OF DELETE!!!");
needs to be
printf("IN THE BEGINNING OF DELETE!!!\n");
^^ note the newline
The reason is because stdio does not flush stdout until it sees a newline. If you add that newline, you should see the printf when the code enters the function. Without it, the program could crash, the stdout buffer would not have been flushed and would not see the printf.
Your code seems to have lots of implementation flaws. As a general advice I would recommend using some standard well-tested queue support library and static code analyzers (in this case you would even find dynamic analyzer valgrind very helpful, I guess).
For example, if implementation of destroy_node(ptr) is equivalent to free(ptr), then your code suffers from referencing destroyed data (or ,in other words, garbage) in this code snippet:
while(curr_ptr != NULL) {
if (curr_ptr->data == data) {
result = 1;
if (curr_ptr->next != NULL) {
temp_ptr = curr_ptr;
destroy_node(temp_ptr);
prev_ptr->next = curr_ptr->next; //<- curr_ptr is still in stack
//or register, but curr->next
//is garbage
// what if curr_ptr is first node? did you forget to update queueref.first?
} else {
temp_ptr = curr_ptr;
queueref.last = prev_ptr;
prev_ptr->next = NULL;
destroy_node(temp_ptr);
}
// if you you need to destroy only one node - you can leave the loop here with break;
}
curr_ptr = curr_ptr->next; /// assigning garbage again if node is found
prev_ptr = prev_ptr->next;
The reason why using destroyed data can work in * most * (if I can say that, basically this is unpredictable) cases is that the chances that this memory can be reused by other part of program for dynamically allocated data can vary on timings and code flow.
PS
Regarding cryptic messages in the Windows box - when program crashes OS basically generates crashdump and prints registers (and dumps some relevant memory parts). Registers and memory dumps can show the place of crash and immediate register/stack values but you have to now memory map and assembler output to understand it. Crashdump can be loaded to debugger (WinDbg) together with unstripped binary to check stactrace and values of local variables at the moment of crash. All these I described very very briefly, you could find tons of books / guides searching for "windows crash or crashdump analysis"
I'm getting an error in valgrind and don't know what is wrong.
The error is:
valgrind output:
==1112== Conditional jump or move depends on uninitialised value(s)
==1112== at 0x402BF0D: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
And it states the problem occurs on line 226:
if(reallocate ==TRUE)
{
char** temp_values = NULL;
temp_values = (char**) realloc(theBoard->_values, theBoard->_size_r*sizeof(char*) );
if(temp_values!=NULL)
{
theBoard->_values = temp_values;
} else
{
reportError(MEM_OUT);
return FALSE;
}
int i = 0;
for (i=0; i<theBoard->_size_r; i++)
{
char* temp_values_c = NULL;
HERE( line 226)-> temp_values_c = realloc(theBoard->_values[i], theBoard->_size_c*sizeof(char) );
if(temp_values_c != NULL)
{
theBoard->_values[i] = temp_values_c;
} else
{
reportError(MEM_OUT);
return FALSE;
}
}
// initialize extra memory
if(row_out_bound)
{
init(theBoard,prev_size_r,0);
}
if(col_out_bound)
{
init(theBoard,0, prev_size_c);
}
}
Why is this happening and how can i fix it?
The problem is theBoard->_values[i] is not initialized since it comes straight from realloc (temp_values = ...).
EDIT
Can you elaborate please?
I thought you'd never ask. The function realloc returns a chunk of memory of the specified size, with no guarantees regarding its contents. So for all practical purposes you should assume anything realloc returns contains garbage. In your code you take that (potential) garbage and on line 226 you tell realloc:
Here's this pointer that's like totally valid and all. It's NULL or I previously obtained it from malloc. Can you realloc it to this size? And that's not true! The actual value contained by theBoard->_values[i] could be anything.
What you want is a loop that does theBoard->_values[i] = NULL, or maybe use malloc instead of realloc on line 226.
The following deleteNode function when I run the program gets these:
* glibc detected free(): invalid next size (normal): 0x000000000103dd90 **
Even i make the ' free(here); ' a comment,i get the above message.
I dont think that the other 'free' calls provokes a problem like that. But I cant see why this would be wrong. :/
struct List *deleteNode(int Code,int i,char* Number)
{
struct List *here;
here=Head;
for (here; here!=Tail; here=here->next)
{
if ( (here->number==Number) && (here->code==Code) )//found node on the List
{
if (here->previous==Head) //delete from beginning
{
Head=here->next;
here->next->previous=Head;
}
else if (here->next==Tail) //delete from the end
{
here->previous->next=Tail;
Tail=here->previous;
}
else //delete from the middle of the list
{
here->previous->next=here->next;
here->next->previous=here->previous;
}
break;
}
}
free (here);
}
EDIT:
if i used and understand valgring well then the problem is on my main function.
i have also there some 'free' but i changed deleteNode before this message so i thought that the problem was on the deleteNode function.
Now,there is no free() invalid next size.... but unfortunately this:
glibc detected * : double free or corruption (out): 0x00007fff1aae9ae0 *
:(
A part of the main:
FILE *File;
if ( ( File=fopen("File.txt","r")) !=NULL )
{
int li = 0;
char *lin = (char *) malloc(MAX_LINE * sizeof(char));
while(fgets(lin, MAX_LINE, eventFile) != NULL)
{
token = linetok(lin, " ");
if(token != NULL)
{
int i,code,nodeID;
char *number;
char *event;
for(i = 0; token[i] != NULL; i += 1)
{
code=atoi(token[0]);
strcpy(event,token[1]);
nodeID=atoi(token[2]);
strcpy(number,token[3]) ;
int i;
if (!strcmp(event,"add"))
{
add_to_List(code,i,number);
}
else if(!strcmp(event,"delete"))
{
deleteNode(eventNo,i,number);
}
free(event);
free(phoneNumber);
}
free(token);
}
else
{
printf("Error reading line %s\n", lin);
exit(1);
}
}
}
else
{
printf("Error opening file with the events.\nEXIT!");
exit(0);
}
debugging it...
multiple definition of main'
pro:(.text+0xce0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.4.1/crtend.o:(.dtors+0x0): multiple definition ofDTOR_END'
pro:(.dtors+0x8): first defined here
/usr/bin/ld: warning: Cannot create .eh_frame_hdr section, --eh-frame-hdr ignored.
/usr/bin/ld: error in pro1(.eh_frame); no .eh_frame_hdr table will be created.
collect2: ld returned 1 exit status
"Invalid next size" means that glibc has detected corruption in your memory arena.
You have overwritten valuable accounting information that's stored in between your allocated blocks.
With each block that malloc gives you, there is some accounting information stored close by. When you overwrite this information by, for example, writing 128 characters to a 20-character buffer, glibc may detect this the next time you try to free (or possibly allocate) some memory.
You need to find the root cause of this problem - it's not the free itself, that's just where the problem is being detected. Somewhere, some of your code is trashing memory and a memory analysis tool like valgrind will be invaluable here.
If the node is not found in the list, you will free the Tail node at the end of the function, without updating Tail to point to anything valid again.
Further using the list and the now deallocated Tail can easily result in memory corruption that might later be detected by glibc with a message like the one you got.
Also note that in (here->number==Number) you are comparing two pointers, not the values those pointers point to. I'm not sure if that's what you want.