LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-18-2023, 03:12 PM   #1
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,146

Rep: Reputation: 392Reputation: 392Reputation: 392Reputation: 392
getline throwing uninitialized value in valgrind


Relavant code.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jmgeneral.h>

#define TESTFILE "testfile.txt"

int line_num_chars(char * str);

int main()
{

  FILE * file = fopen(TESTFILE, "r");
  int max_chars = 0;
  int len = 0;
  char * buffer = NULL;
  bool keepgoing = true;

  while (keepgoing) {
    char * tempbuf = getline_mem_alloc(file);
    // allocate second memory. trying to make valgrind happy
    buffer = allocate_string_mem(tempbuf);

    // clear temp buffer asap to limit memory usage
    free(tempbuf);
    tempbuf = NULL;

    len = strlen(buffer);

    if (len > max_chars) {
      max_chars = len;
    }

    free(buffer);
    buffer = NULL;

    if (feof(file)) {
      keepgoing = false;
    }
  }

  fclose(file);
  file = NULL;

  printf("total top = %d\n", max_chars);
  return(0);
}
Code:
char * getline_mem_alloc(FILE * file)
{
  assert(file);

  // declare & initialize
  size_t buflen = 0;
  char * buffer = NULL;
  buflen = getline(&buffer,
                   &buflen,
                   file);

  // return buffer
  return(buffer);
}
Code:
char * allocate_string_mem(const char * str)
{
  assert(str);
  int chars = 0;

  char * retstr = (char*)malloc(strlen(str) * sizeof(char) + 1);
  for (int i = 0; i <= strlen(str); i++) {
    retstr[i] = '\0';
    chars++;
  }
  strncpy(retstr, 
          str,
          chars);
  assert(retstr);
  return(retstr);
}
Output

Code:
valgrind -s --leak-check=full --track-origins=yes ./a.out 
==48843== Memcheck, a memory error detector
==48843== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==48843== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==48843== Command: ./a.out
==48843== 
==48843== Conditional jump or move depends on uninitialised value(s)
==48843==    at 0x48467E5: __strlen_sse2 (vg_replace_strmem.c:496)
==48843==    by 0x48543B2: allocate_string_mem (in /usr/local/lib/libjmgeneral.so)
==48843==    by 0x109205: main (in /home/jason/Documents/a.out)
==48843==  Uninitialised value was created by a heap allocation
==48843==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==48843==    by 0x48DFBAE: getdelim (iogetdelim.c:62)
==48843==    by 0x4853C79: getline_mem_alloc (in /usr/local/lib/libjmgeneral.so)
==48843==    by 0x1091F5: main (in /home/jason/Documents/a.out)
==48843== 
==48843== Conditional jump or move depends on uninitialised value(s)
==48843==    at 0x4846DF3: __strncpy_sse2_unaligned (vg_replace_strmem.c:602)
==48843==    by 0x48543E7: allocate_string_mem (in /usr/local/lib/libjmgeneral.so)
==48843==    by 0x109205: main (in /home/jason/Documents/a.out)
==48843==  Uninitialised value was created by a heap allocation
==48843==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==48843==    by 0x48DFBAE: getdelim (iogetdelim.c:62)
==48843==    by 0x4853C79: getline_mem_alloc (in /usr/local/lib/libjmgeneral.so)
==48843==    by 0x1091F5: main (in /home/jason/Documents/a.out)
==48843== 
total top = 29
==48843== 
==48843== HEAP SUMMARY:
==48843==     in use at exit: 0 bytes in 0 blocks
==48843==   total heap usage: 13 allocs, 13 frees, 6,274 bytes allocated
==48843== 
==48843== All heap blocks were freed -- no leaks are possible
==48843== 
==48843== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==48843== 
==48843== 1 errors in context 1 of 2:
==48843== Conditional jump or move depends on uninitialised value(s)
==48843==    at 0x4846DF3: __strncpy_sse2_unaligned (vg_replace_strmem.c:602)
==48843==    by 0x48543E7: allocate_string_mem (in /usr/local/lib/libjmgeneral.so)
==48843==    by 0x109205: main (in /home/jason/Documents/a.out)
==48843==  Uninitialised value was created by a heap allocation
==48843==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==48843==    by 0x48DFBAE: getdelim (iogetdelim.c:62)
==48843==    by 0x4853C79: getline_mem_alloc (in /usr/local/lib/libjmgeneral.so)
==48843==    by 0x1091F5: main (in /home/jason/Documents/a.out)
==48843== 
==48843== 
==48843== 1 errors in context 2 of 2:
==48843== Conditional jump or move depends on uninitialised value(s)
==48843==    at 0x48467E5: __strlen_sse2 (vg_replace_strmem.c:496)
==48843==    by 0x48543B2: allocate_string_mem (in /usr/local/lib/libjmgeneral.so)
==48843==    by 0x109205: main (in /home/jason/Documents/a.out)
==48843==  Uninitialised value was created by a heap allocation
==48843==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==48843==    by 0x48DFBAE: getdelim (iogetdelim.c:62)
==48843==    by 0x4853C79: getline_mem_alloc (in /usr/local/lib/libjmgeneral.so)
==48843==    by 0x1091F5: main (in /home/jason/Documents/a.out)
==48843== 
==48843== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
I've tried many variations thinking it was something with my functions. I can do this via fgets no problem no errors. but something about my getline here. I've googled, seems to be an occasional problem but haven't found a solution that works yet.
 
Old 09-18-2023, 03:49 PM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
Code:
char * allocate_string_mem(const char * str)
{
  assert(str);
  int chars = 0;

  char * retstr = (char*)malloc(strlen(str) * sizeof(char) + 1);
  for (int i = 0; i <= strlen(str); i++) {
    retstr[i] = '\0';
    chars++;
  }
  strncpy(retstr, 
          str,
          chars);
  assert(retstr);
  return(retstr);
}
Please optimalize this function as it is extremely slow. (When it is done, simple drop it, there is a standard strdup function.)
 
1 members found this post helpful.
Old 09-18-2023, 07:49 PM   #3
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,269
Blog Entries: 24

Rep: Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196
Valgrind knows the memory has been allocated within getline() and assigned to pointer buffer, but seems unaware that it has been written by getline(). Any attempt to read it produces a valgrind error, but you can write to it and once you do the program completes and valgrind says all is OK. For example, add strcpy(buffer,"some text") immediately after the call to getline() (be sure not to exceed buflen).

I am not a frequent valgrind user so cannot say whether this is to be expected or why it happens. My searches turned up other odd valgrind behaviors with getline, some version dependent, but not this exactly.

Hope it helps.

Last edited by astrogeek; 09-18-2023 at 08:17 PM. Reason: grammar
 
1 members found this post helpful.
Old 09-18-2023, 09:08 PM   #4
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,146

Original Poster
Rep: Reputation: 392Reputation: 392Reputation: 392Reputation: 392
Ok. I tried a few more things. And I dumped those 2 alloc functions I had written and replaced with strdup in my library.

Thank you both.

It works fine if I don't try to operate on the tempbuf return. No errors. But as soon as I want to run an operation on it, strlen or whatever so far seems to toss that error.

Last edited by jmgibson1981; 09-18-2023 at 09:09 PM.
 
Old 09-18-2023, 10:10 PM   #5
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
It might give more information, if you compile your shared library with option `-g`.
Or for debugging you could directly link your rutins into the executable.

PS: don't do this with 'buflen':
Code:
buflen = getline(&buffer, &buflen, file);
Instead add error-checks after `fopen` and `getline`

Last edited by NevemTeve; 09-18-2023 at 10:16 PM.
 
1 members found this post helpful.
Old 09-18-2023, 11:41 PM   #6
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,146

Original Poster
Rep: Reputation: 392Reputation: 392Reputation: 392Reputation: 392
Ok done. The main function is just me fiddling around. I normally run tests on file ops. I did replace that buflen thing with a test with error message & bail out on fail.
 
Old 09-19-2023, 12:45 AM   #7
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
E.g.:
Code:
ssize_t strLen = getline(&buffer, &buflen, file);
 
Old 09-19-2023, 03:25 PM   #8
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,269
Blog Entries: 24

Rep: Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196
Could not get this off my mind as I did not really understand it on first look, and knew it, and it did not seem reasonable that valgrind would miss an initialization.

NevemTeve is on the right track. You need to test for unsuccessful call to getline(...), it returns -1 for both errors and for EOF, and it is the EOF that is causing the problem.

You are not using buflen or the returned character count, so just test for -1.

The acual cause of the valgrind error is, even though unsuccessful or EOF, a buffer will have been allocated and needs to be free()d and not further used.

So, along with the change from allocate_string_mem() to strdup() and a test of returned pointer, this should fix it up properly:

Code:
char * getline_mem_alloc(FILE * file)
{
  assert(file);

  size_t buflen = 0;
  char * buffer = NULL;
  if(getline(&buffer,
                   &buflen,
                   file)==-1)
        {
        free(buffer);
        buffer = NULL;
        }
  return(buffer);
}
Note: I have not looked at your github changes so above applies to your originally posted code.

Last edited by astrogeek; 09-19-2023 at 04:49 PM.
 
2 members found this post helpful.
Old 09-19-2023, 04:58 PM   #9
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,146

Original Poster
Rep: Reputation: 392Reputation: 392Reputation: 392Reputation: 392
Git pushed. I am very grateful to you folks. Works no errors now.

*EDIT* in a previous post I mentioned about needing to research return codes. its getting more necessary quickly.

Last edited by jmgibson1981; 09-19-2023 at 07:11 PM.
 
Old 09-19-2023, 05:02 PM   #10
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,269
Blog Entries: 24

Rep: Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196Reputation: 4196
You are very welcome, and thanks for the opportunity to improve my poor valgrind skills!
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
pthread_cond_wait sys call is getting assert failure when using helgrind tool in valgrind but not failed with memcheck tool with valgrind kalyan.vangipurapu Programming 7 06-21-2017 08:28 AM
Valgrind is throwing error "failed in UME with error 22 (Invalid argument)." vamsi9042 Programming 1 11-06-2013 04:57 AM
Use of uninitialized value...of an initialized value? macaswell Programming 1 01-06-2013 09:35 AM
difference between value *value and value * value PoleStar Linux - Newbie 1 11-26-2010 03:37 PM
cricket - uninitialized value in script imanassypov Linux - Networking 0 03-21-2006 09:19 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:52 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration