Segfault 11 on a decimal to binary function - c

I have a function that converts decimal to binary and returns a char * of a binary:
void decimal2binary(int decimalNum, int size, char * charPtr){
int decimalTemp = decimalNum;
int modNum;
for(int sizeTemp = size; sizeTemp >= 0; --sizeTemp){
modNum = decimalTemp >> sizeTemp;
if(modNum & 1){
strcat(charPtr, "1");
}else{
strcat(charPtr, "0");
}
}
}
When I try to test it in main, I get the correct out put as and then "Segmentation fault 11" with gcc compiler:
In int main() :
char testArr[] = "test";
char * foo = testArr;
decimal2binary(10,7, foo);
printf("%s\n", foo);
printf("asdasds\n");
Result :
test00001010
asdasds
Segmentation Fault: 11
Any ideas?

The array you pass in has a size of 5 - "test\0".
It doesn't "work" as you are writing in an invalid memory location.
More like undefined behavior.
EDIT:
If you can't tell the size of the buffer to pass in, a suggestion might be to use realloc and grow your array. Return the pointer, but remember to free the allocated memory.

You are getting segmentation fault for attempting to write on memory addresses that are not
inside your memory segment.
Use an array of bigger size or even better use pointers and keep on realloc'ing new space
as needed.

Related

Segmentation fault when trying to free memory

I have below code where I have commented when I get segmentation fault and when not.
Originally I got segmentation fault and then I could figure out that probably I cannot initialize my char pointer locations like "abcd". But I am not able to understand - WHY?
I thought testString = "abcd"; will put a at first memory address, b at second and so on ...
Segmentation fault occurs when trying to free memory, based on how I initialize memory location.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* testString = malloc(sizeof(char) * 5);
printf("Size of char is: %d\n", sizeof(char));
printf("Size of int is: %d\n", sizeof(int));
for(int i = 0; i < 5; i++)
{
printf("Pointer addresses are: %p\n", testString + i);
}
char* tempPtr = testString + 2;
printf("My temp pointer address = %p\n", tempPtr);
// This gives me segmentation fault ....
testString = "abcd";
// This will not give me segmentation fault ....
//int count = 65;
//for(int i = 0; i < 5; i++)
//{
// testString[i] = count + i;
//}
printf("Printing character...\n");
for(int i = 0; i < 5; i++)
{
printf("Characters are: %c\n", testString[i]);
}
printf("Freeing memory...\n");
free(testString);
//printf("Access after freeing >>%c<<\n", tempPtr[0]);
//free(testString);
}
Based on #M.M. and #Jonathan's comment I understood that with testString = "abcd"; my testString will point to a memory location where string "abcd" was created and since I didn't malloc'ed it I cannot free it. Also, since my original pointer to heap memory (which I got using malloc) is gone, so it is waste of memory or memory lead.
So, does it means that when I use printf statement like printf("Printing character...\n");, this is also a memory leak? Then how do I avoid it? Looping and inserting into char* is certainly a bad idea.
this line:
testString = "abcd";
is overlaying the pointer given by the call to malloc() with the address of the string literal: "abcd" this results in a memory leak because the original pointer to the allocated memory is lost.
In C, when copying a string, it 'should' be handled by the functions: strcpy() and strncpy() which will not corrupt the pointer contained in testString.
strcpy( testString, "abcd" );
strncpy( testString, "abcd", strlen( "abcd" ) );
Naturally, once the pointer to the allocated memory has been overlayed/destroyed by the assignment statement: testString = "abcd";, the new value placed into testString must not be passed to free()
the seg fault would be happening at the call to free(), not at the incorrect assignment of a new pointer to testString.
Using printf is not a memory leak. Memory leaks occur when a pointer is allocated via malloc [or, herein, strdup] and there is no corresponding free call for it.
Also, trying to free a pointer that has not been allocated is another type of error. It [probably] won't segfault, but free will complain.
Here's a simplified version of your program that illustrates some of the ways you can do this:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int opt_segv;
char *temp = "abcd";
void
dostr(char *str,int modflg)
{
printf("\n");
printf("dostr: %s\n",str);
if (modflg)
str[modflg] = 'm';
printf("dostr: %s\n",str);
}
void
test1(void)
{
int len;
char *testString;
len = strlen(temp);
testString = malloc(len + 1);
strcpy(testString,temp);
dostr(testString,1);
free(testString);
}
void
test2(void)
{
char *testString;
testString = strdup(temp);
dostr(testString,2);
free(testString);
}
void
test3(void)
{
char *testString;
// passing a pointer to a string _constant_ -- do _not_ modify
testString = temp;
dostr(testString,opt_segv ? 3 : 0);
}
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 's': // generate segfault
opt_segv = 1;
break;
}
}
test1();
test2();
test3();
return 0;
}
You can run the program with -s to simulate the string constant modification that caused your segfault.
This question has content relevant to answer of my question but doesn't have detailed answer. #Jonathan's comments answers all my questions but he hasn't put forward a detailed answer so I am writing my answer so that folks who will visit further can have detailed explanation:
I created a pointer and allocated some space on "heap segment" of the memory, now my pointer was pointing to that memory location on heap.
Code relevant for all this is - char* testString = malloc(sizeof(char) * 5);.
Now, when I dis this - testString = "abcd"; then string "abcd" is created in "text/code segment" (or in some implementation data segment) of the memory and memory address is returned and assigned to my pointer testString.
What happens is that my original pointer which was pointing a memory location on heap is lost and the pointer started pointing to a memory location on text/code segment of the memory.
Implication of all this:
It has resulted in memory leak because my original pointer which was pointing to the heap memory is lost, so now I have no way to free that heap memory and hence memory leak.
When I will try to free that memory using free(testString); then I will get segmentation fault (this is exactly what has happened to me) because free() can only be used to free the memory which is allocated using either malloc, calloc or realloc. Now, since the pointer testString is pointing to a memory location on text/code segment and I had not allocated that memory using some C memory allocation method, so I cannot free it using free() and if I do so then I get segmentation fault.
When I do testString = "abcd" (when testString is a pointer) then I cannot access the memory location pointed by testString because the memory allocated is read-only in text/code segment of the memory. So, testString[0] = 'x' will also result in segmentation fault.
What happens when I do printf("hello, world")?:
This will create "hello, world" string as read-only in text/code segment of memory. I verified that it does create in text/code segment in C99 implementation using size command.

Getting seg fault when trying to decrement my environment variable in C

Total C noob here. I know there is something wrong with my sprintf_wrapper method because before I introduced it everything was working fine. The point of the function is to take a string buffer and a number and change the string buffers value to "WHALE=[num]". I then use this new string with putenv method.
The code results in "Segmentation fault (core dumped)", I believe it occurs after sprintf_wrapper is called.
Main Method
int main(void) {
getP0Info();
putenv("WHALE=7");
forkProcesses();
int whale = atoi(getenv("WHALE"));
char new_env[50];
sleep(1);
printf("P0: %d\n", whale);
whale = whale - 1;
sprintf_wrapper(new_env, whale);
putenv(new_env);
return 0;
}
sprintf_wrapper
void sprintf_wrapper(char* str, int num) {
char buffer[10];
str = "WHALE=";
sprintf(buffer,"%d", num);
strcat(str,buffer);
}
You're assigning a string constant to the str variable, then attempting to to append to it. Because string constants typically live in read only memory, this commonly causes a core dump.
Do this instead:
void sprintf_wrapper(char* str, int num) {
sprintf(str,"WHALE=%d", num);
}
sprintf_wrapper(new_env, whale);
You are appending to a string literal, which is read-only memory.
This generates a segmentation fault because you write into memory that is not supposed to be written into.
str = "WHALE=";
Thats a read only string literal.

Get a segmentation fault through argv on purpose

I want to write a small program, which, by user input through argv, gets a segmentation error. I am quite new to C but I think the following code does the job:
int main(int argc, char *argv[])
{
int bufferSize;
char * buffer[100];
unsigned int i;
if (argc > 1) {
bufferSize = atoi(argv[1]);
for (i = 0; i < bufferSize; ++i)
*( buffer + i ) = i;
}
return 0;
}
My idea is that the program intialize (?) a pointer to a buffer of a specific size. If the user then input a number larger then the buffer size it will write to uninitialized memory, hence get a seg. fault. Is this reasoning correct whatsoever?
Ps. When compiling,I get a assignment makes pointer from integer without a castwarning, can someone maybe tell me why that happens? Thanks
The most traditional way to purposely get a segmentation fault, that I've seen, is to write to NULL, e.g. something like:
*((char *) NULL) = 0;
You can use a command line argument as a simple boolean value to see if this should be done or not.
Note that writing to NULL is not actually guaranteed to cause a crash, it's simply undefined behavior so basically anything could happen (including causing nasal demons).
The warning is because you have an array of pointers, and try to assign an integer to a pointer in the array.
char * buffer[100]; is an array of pointer which points to some garbage locations by default.
Here *( buffer + i ) = i; you are trying to deference that area which doesn't belongs to you.
My guess is that, you wanted to create a buffer. so
char buffer[100]; is enough.
I would not worry about writing to cause a segmentation fault. Reading is sufficient enough. You stand a better chance of causing a segfault if the buffer is on the heap. This application fairly reliably segfaults for negative inputs less than -10 for me.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(int argc, char* argv[])
{
static const int array[10] = {0,1,2,3,4,5,6,7,8,9};
int * const heapArray = malloc(sizeof(array));
memcpy(heapArray,array,sizeof(array));
const int index = atoi(argv[1]);
printf("%i\n",heapArray[index]);
free(heapArray);
return 0;
}
The problem is, the result of malloc() can be much much larger than the requested size for most systems. So even for large values it does not segfault, it just returns whatever happens to be there in memory.
ericu#eric-phenom-linux:~$ ./segfault -5
Segmentation fault (core dumped)
ericu#eric-phenom-linux:~$ ./segfault 11
0
ericu#eric-phenom-linux:~$ ./segfault 100
0
ericu#eric-phenom-linux:~$ ./segfault 100
0
ericu#eric-phenom-linux:~$ ./segfault 1000
0
ericu#eric-phenom-linux:~$ ./segfault 10000
0
ericu#eric-phenom-linux:~$ ./segfault 100000
Segmentation fault (core dumped)

String copy(strcpy)

I have the following code.
#include <string.h>
#include <stdio.h>
int main()
{
char * l;
*l = 'c';
*(l+1) = 'g';
*(l+2) = '\0';
char *second;
strcpy(second, l);
printf("string: %s\n", second);
}
When I run it is says:
The output says "Segmentation fault"....any suggestions??
Thanks
l is an uninitialized pointer; you can't dereference it. You should allocate enough space to write its contents (statically (1) or dynamically (2)).
char l[3]; /* (1) */
#include <stdlib.h>
char *l = malloc(3); /* (2) */
It is the same error with strcpy: second is an unitialized pointer, you can't write into it.
You will learn to despise the Segmentation Fault error...
It's usually called when you try to access memory that is not yours. Most common occurrence would be when you try to access an array index that is out of bounds.
char *l just creates a pointer to a char. What you want is a string, which in C is defined as an array of chars. So when you try to access the next location in memory of whatever l is pointing to (which will probably just be garbage), you're going to access memory that isn't yours, thus Segmentation Fault
You could get memory with malloc or point the pointer to an already existing variable.
char word[3];
char *l;
l = word;
Now you can do such assignments:
*l = 'c';
*(l+1) = 'g';
*(l+2) = '\0';
but now that you want to copy it to another pointer, this pointer must be pointing to another string or you should allocate memory for it.
char *pointer_to_second;
char second[3];
pointer_to_second = second;
or if you prefer to get dynamic memory, change the 3 lines above be this one bellow:
char *pointer_to_second = malloc(sizeof(char) * 3);
after that you can do what you wanted:
strcpy(pointer_to_second, l);
But remember, if you are using a C compiler you must declare all variables at the beggining, otherwise you will get an error. If you are using a C++ compiler you won't have to concern about it.
Segmentation fault happens when you try to access a field that doesn't belong to your vector. For example, if you try this:
printf("The value in position 3 of my pointer is %c\n", *(l + 3));
You will probably get an error, because you pointer have 3 positions and you are trying to acess the 4th one.

scanf and point to int* segmentation fault

I call my program and it is to read a bunch fo integers from the standard input
int main() {
int* s;
derp(s);
return 0;
}
void derp(int *size) {
scanf("%d", size);
}
why is this code causing a segmentation fault?
int* s;
derp(s);
What does s point to? To random garbage memory since its not initialized. You should do this instead:
int s;
derp(&s);
or you could allocate storage space using malloc:
int* s = malloc( sizeof(int) );
derp(s);
free(s);
Because you need to initialize s.
Add this:
s = malloc(sizeof(int));
Remember to free(s) when you're done.
s needs to be initialized using malloc(). As it is now, s points to some random crap somewhere in memory.

Resources