ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm writing a simple program to read in a file of one word per line and store that word into a node of a linked list then print. For simplicity, I removed error checking, etc. Here is the program:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *str;
struct node *next;
};
int
main(void)
{
struct node *current = NULL, *head = NULL, *prev = NULL;
char buffer[256];
char read_buffer[256];
FILE *fp = NULL;
size_t bufsz;
fp = fopen("words.txt", "r");
while ((fgets(read_buffer, sizeof(read_buffer), fp)) != NULL)
{
bufsz = strlen(read_buffer);
current = malloc(sizeof(struct node));
current->str = malloc(bufsz);
strncpy(current->str, read_buffer, bufsz);
current->next = NULL;
if (head == NULL)
head = current;
else
prev->next = current;
prev = current;
}
fclose(fp);
current = head;
while (current != NULL)
{
printf("%s", current->str);
current = current->next;
}
current = head;
while (current != NULL)
{
head = current->next;
free(current->str);
free(current);
current = head;
}
return 0;
}
Here is the file it reads (words.txt):
Quote:
Red
Orange
Yellow
Green
Blue
Indigo
Violet
Which works as expected.
However, I originally had a small bug. For this line:
Quote:
strncpy(current->str, read_buffer, bufsz);
I originally wrote:
Quote:
strncpy(current->str, buffer, bufsz);
So, although each word was being transferred from the file into read_buffer, read_buffer wasn't being transferred to the memory pointed to by current->str.
When I run the buggy version all that happens is I get back a prompt but I expected garbage values to be printed since buffer is being used uninitialized.
I created a smaller version of this program (only creates one node and doesn't read from a file) to see if my expectation was correct and it was:
Why isn't the original buggy version printing garbage values? I feel like I could be missing something quite obvious but I can't figure it out. Any help would be greatly appreciated.
I ran both programs through GDB and printed the contents of the buffer in the first program which started with:
Code:
\003
Which is the octal value for 'end of text'. I can't remember the value for the second program but it wasn't \003 or \000.
Running the first program through GDB a second time and printing the contents of buffer it then started with \000, the value for the Null character.
I added this statement:
Code:
printf("d\n", buffer[0]);
After the buffer declaration in each program in my OP.
For the first one I got:
Quote:
0
and for the second one I got:
Quote:
46
.N=ö
So in the first instance I'm getting the decimal value for the Null or for the 'end of text' character and in the second instance I'm not which explains the results I was getting.
Why does this only seem to happen with the first program and not the second? Are the programs using the same region of memory over and over again? If I ran these programs enough times would the results change? I supposed I could write a script to test this out.
Why does this only seem to happen with the first program and not the second? Are the programs using the same region of memory over and over again? If I ran these programs enough times would the results change? I supposed I could write a script to test this out.
Since buffer is uninitialized, every time you change the program, or change how it is run (with/without the debugger), the uninitialized value may change.
The moral is: never read an uninitialized variable. gcc is very good at detecting uninitialized variables (compile with -Wall).
Ed
Since buffer is uninitialized, every time you change the program, or change how it is run (with/without the debugger), the uninitialized value may change.
The moral is: never read an uninitialized variable. gcc is very good at detecting uninitialized variables (compile with -Wall).
Ed
Much appreciated. I always compile with -Wall and buffer is used in another part of the program that I omitted. It was just a mistake on my part that I read from it. I thought buffer's contents, not being initialized, would've changed more regularly and buffer in the first program wouldn't have started with either /000 or /003 as consistently as it did, so I thought comparing those two programs like I did was enough. I'll never make such assumptions again.
If really interested, check gcc's manpage and search for -W and also read which flags -Wall does include.
There seem to be some new tendencies where compilers do initialize variables to zero. There are compile switches, however on someone else's question, the same uninialized condition occurred for them, but I checked on my system and found with normal compilation and no added flags, it was clearing local variables. Either case, I recommend initializing variables before using them.
If really interested, check gcc's manpage and search for -W and also read which flags -Wall does include.
There seem to be some new tendencies where compilers do initialize variables to zero. There are compile switches, however on someone else's question, the same uninialized condition occurred for them, but I checked on my system and found with normal compilation and no added flags, it was clearing local variables. Either case, I recommend initializing variables before using them.
Yes, I'm reasonably sure there is nothing in the C specification where variables are initialized to anything (and probably nothing that says they can't be) so it would be a mistake to have an expectation of a known value in uninitialized variables.
Well, 'uninitialized' doesn't mean 'source of random data'. Your program runs in separate virtual memory, where memory pages are zero-initialized by the kernel (for security reasons: you're not supposed to see any data the previous program might have left there). So if your automatic variable (that exists on the stack) contains non-zero value, then it came from your own program.
Yes, I'm reasonably sure there is nothing in the C specification where variables are initialized to anything (and probably nothing that says they can't be) so it would be a mistake to have an expectation of a known value in uninitialized variables.
This seems to be the salient part of the C11 standard: section 6.7.9-10
Quote:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
...
So, short answer: if you want to be lazy, define it as static.
You probably don't want to be putting large buffers on the stack anyway, so unless you have some thread-safety issues to worry about, or you're doing some recursion, static might not be such a bad idea.
@Mechanikx, if I may make a suggestion: instead of malloc() and strncpy()
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.