Why not able to create segmentation fault in second program?
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.
Why not able to create segmentation fault in second program?
Had posted the below question earlier here, where was advised to post it in a separate thread titled: What is memory-garbage and how to avoid it?
Though am confused as never intended to have the memory garbage as the issue, and assume that @NevemTeve wanted me to use the : free() to free the dynamically allocated memory.
However, the intent of my question was different, as asked about why segmentation fault occurred in one program's running, and not in the other; though both have similar pointer assignment.
The first program (buggy.c) has invalid assignment:
Code:
int *noptr = NULL;
which if would replace by :
Code:
int *noptr;
then no error of 'segmentation fault' would occur; that occurs due to no address assigned to: *noptr, hence any value assignment is causing the given error.
Wanted to create a similar error in the second program (bug_c.c) but could not get the same fault by the code line :
Code:
char *noptr = 'c';
as that now gives error in compilation.
Code:
$ g++ -o bug_c -g bug_c.c
bug_c.c: In function ‘int main()’:
bug_c.c:6:18: error: invalid conversion from ‘char’ to ‘char*’ [-fpermissive]
6 | char *noptr = 'c';
| ^~~
| |
| char
The codes for the two files : buggy.c, bug_c.c are given belwo:
buggy.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int *ptr = (int *)malloc(sizeof(int)); //not a memory garbage problem, as this line is not an issue, as can have another version with this line removed, and the for-loop removed; and the entire body of the main() replaced by:
//int i = 5; int * noptr = NULL; *noptr = i;
// still the same error of segmentation fault would occur.
// $ ./buggy
// Segmentation fault (core dumped)
int *noptr = NULL;
for (int i=0; i<10; i++) {
if (i == 5) {
*noptr = i;
}
else {
*ptr = i;
}
printf("i is %d\n", i);
}
}
It gives run-time error of Segmentation fault; after compiling using the command: $ g++ -o buggy -g -Wall buggy.c.
Code:
$ ./buggy
i is 0
i is 1
i is 2
i is 3
i is 4
Segmentation fault (core dumped)
With this line you will have an uninitialized variable, so its value will be wathever random garbage is in the used memory/register when the function starts running.
Also you seem to think you have a right to get a Segmentation Fault whenever you have some bug. That is a false assumption.
Due to the modification of the commented code-line, the program executes smoothly:
Code:
$ ./bug_c
i: 5, *noptr:5
That's just random luck.
A pointer, is like your finger, point it somewhere. Where it is pointing is the value.
Since you did not initialize the pointer, it's pointing to some arbitrary memory location, where "now" that has a value of '5'.
The problem is, the memory the pointer is located in probably doesn't get changed much unless you run a bunch more programs. The location that pointer, points to, also has that same fortune. So you can run this a lot and still see '5'.
That doesn't mean it is correct.
The fact that you declared a pointer variable reserves space for it on the stack.
The contents of the pointer itself are random unless you initialize it by assigning a valid address for it to point to.
Above where you initialized it to NULL is actually valid in some way. Just that the finger is pointing to 0x00000000 which is an illegal address to try to modify, hence why you get the segmentation violation.
What instead you need is a variable to actually point to.
Code:
int value;
int *noptr = &value;
This is correct.
While your second code doesn't always cause a segment violation, it is far worse, it is modifying memory it has no idea what program owns it,
Back to your finger as a pointer, say you're picking people for a team. If you initialize your finger/pointer, you point to someone you want on your team, and it works correctly. If you initialize your finger to point to nowhere, or an invalid address, your hand locks up saying, "I don't know what to do!" If you initialize you finger/pointer to a random, but fortunately valid address, when you select your team member, you may get "bunny rabbit", "cloud", something valid, but random.
Quote:
Originally Posted by ajiten
Code:
char *noptr = 'c';
'c' is not a location, it is a value. A character pointer needs to point to a character variable:
With this line you will have an uninitialized variable, so its value will be wathever random garbage is in the used memory/register when the function starts running.
Also you seem to think you have a right to get a Segmentation Fault whenever you have some bug. That is a false assumption.
Request elaboration, as the post #3, by @rtmistler is not clear to me.
Request details: which was the first word you didn't understand?
The part not understood is in the first line, as the rest is a modification of the second program (bug.c) only, i.e.:
That's just random luck.
================================
In fact, you also stated a similar statement as your second line, though in the first line you referred to a different area of 'garbage collection'.
---------------------------------
Want to add that now for the below program, am able to compile, with only a warning:
Code:
warning: initialization of ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
6 | char *noptr = 'c';
| ^~~
Program:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
char *noptr = 'c';
char i = '5';
*noptr = i;
printf("i: %c, *noptr:%c", i, *noptr);
}
Want to add what? Random luck? Undefined behavior?
> am able to compile, with only a warning
That's because variable initialization and assignment are different things, even if they look alike.
Code:
char somechar= 'X';
char *ptr= &somechar; /* initialization of the pointer */
ptr= &somechar; /* assignment to the pointer */
*ptr= 'Y'; /* assignment to pointed character */
Again: take same beginners' C-programming course and/or do the exercises on hackerrank.
Do you not know the difference between a null pointer and an uninitialized pointer?
EDIT: Okay, I'll explain it. Memory is a column in Excel. Nothing is at row zero. A memory address is a row number. Some things you should already know are:
The value of a pointer is a memory address
nothing is at row zero (as I said).
a pointer is a variable, and if you don't specify the value of a variable, then its value is whatever's convenient (effectively, this is random).
So this simply stores the the value zero in the pointer variable:
Code:
int *noptr = NULL;
When you dereference the pointer with the following, and then do an assignment:
Code:
*noptr = i
You're writing the value of i to address zero, where nothing is ever supposed to be stored. The OS detects that and you get a segmentation fault.
If you do this, however:
Code:
int* nopr
Then the value of nopr could be any address.
And then when you do this:
Code:
*nopr = i
You're storing the value of i at that random memory address. This is a bad thing. You might not get a segmentation fault because the OS might not detect it as a problem, but fortunately the compiler does:
Code:
~/Documents/segfault via C v13.2.1-gcc
❯ gcc -Wall bug_c.c
bug_c.c: In function ‘main’:
bug_c.c:19:11: warning: ‘noptr’ is used uninitialized [-Wuninitialized]
19 | *noptr = i;
| ~~~~~~~^~~
bug_c.c:17:10: note: ‘noptr’ was declared here
17 | char *noptr;
| ^~~~~
When you got that warning, you should really have fixed it before continuing.
Unfortunately, when I try to explain background basics like this, the response I get is usually that I'm going "off topic" (I have gotten this reaction from two different individuals). I assume this poster will act more maturely than some others have.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.