Segmentation fault when accessing a c string in a another function - c

I am writing a small program to get familiar with C again.
I have now a part of the program where I am stuck and can not go forward. I have a function where I create a c string and a pointer to the 2nd element of that string. (When it is finished it should receive a pointer to another string)
When I pass this strings to another function which should remove some elements on the first one I always get a segmentation fault. Which should mean, that I can't access that memory. But, if I change the order I pass the strings to the function I get the same error... .
Here is the code:
int analyze_sudoku(const void *self, Sudoku *sudoku) {
for(int i = 1; i < 82; i++)
{
int success = 0;
// All possible values of a column
// This can be rewritten of course but this way
// it makes the intention what this var is for
// very clear in my opinion
char options[10] = {'1','2','3','4','5','6','7','8','9'};
char *chars_in_row;
// The same problem...
// chars_in_row = sudoku->get_row_for_column(sudoku, i);
chars_in_row = &options[2];
printf("In field %d we have this chars in the row: %s\n", i,chars_in_row);
printf("length der chars: %d\n", strlen(chars_in_row));
printf("addresse of the char pointers: %p\n", (void *)chars_in_row);
// After receiving all chars from one row, we remove
// those from the one we have in our options
// HERE IS THE FUNCTION CALL
remove_from_options(options, chars_in_row);
// ... more code follows
}
}
And here is the function where I get my seg fault:
char *remove_from_options(char *options, char *already_in_use) {
puts("Welcome");
printf("Your options: %s\n", options);
// HERE THE SEG FAULT HAPPENS
// as already mentioned the error happens no matter what I give this function
printf("pointer address: %p", (void *)already_in_use);
printf("already in use: %s", already_in_use);
printf("in use länge: %d", strlen(already_in_use));
for(int i = 0; i < strlen(already_in_use); i++)
{
// some code...
}
}

This
char options[10] = {'1','2','3','4','5','6','7','8','9'};
is not a string but array of characters. In C language, strings are actually one-dimensional array of characters terminated by a null character '\0'.
The %s format specifier, in printf(), writes every byte up to and not including the first null terminator. Since the char array option does not have the null character, the printf() must be accessing beyond the size of option array which is leading to segmentation fault.
Try adding the null character at the last of option array, like this:
char options[10] = {'1','2','3','4','5','6','7','8','9','\0'};
EDIT
I totally missed the point that the last index of array option has been initialized with 0. There is no need to explicitly give the null character at the end of option array. OP has accepted this as the answer because this, somehow, resolve the OP's problem. Hence, I can not delete this post. Minimal complete and verifiable example is required to identify the root cause of the problem mentioned by OP.

Related

Segmentation error while returning a pointer from an array using malloc() in C

maybe it's a dumb question but I'm new in C. I'm trying to return a pointer from a function using malloc. I made an array with strtok. Here it's the code of the function from which I'm trying to return the pointer:
int *data(){
int longi=0, *array=(int *) malloc(4 * sizeof(int));
char buffer[1024];
char *aux;
printf("Enter if approved(A) or failed (F) separated by a comma \",\": \n");
fgets(buffer,1023,stdin);
aux=strtok(buffer, ",");
while(aux)
{
array[longi]=aux;
longi++;
aux=strtok(NULL, ",");
}
printf("%s", array[0]);
return array;
}
And here is my main function:
int main(){
int *arr=data();
printf("%s",arr[0]); /*segmentation error */
return 0;
}
The segmentation fault occurs because you are trying to print part of your array as a string (%s). When using %d or %c (with char casting) it does not give that error.
However, it still doesn't make sense, since you are trying to put a pointer to the beginning of a string inside an array of integers. I'd suggest allocating an array of characters instead of integers, and making sure you've got a single character inside aux, then adding it to the array. You also need to make sure you don't accept more than 4 different characters, otherwise you might still have a buffer overflow.
printf when flag is %s is trying to read string from allocated memory, you giving an integer so this why it gives a segfault
replace array[longi]=aux; with array[longi]=atoi(aux); atoi will convert from string to integer, and for both printfs replace %s with %d

Changing Case of a String

I'm new to C and am trying to write a simple function that can take in a string (or array of characters) and convert its case based on the following rules:
The first character should be uppercase.
The remaining characters should be lowercase.
I've written code, but I'm running into segmentation fault errors, and I'm baffled as to what's going wrong. Here's what I've written:
void myFunction(char name[]) {
printf("Before: %s", name);
name[0] = toupper(name[0]); // This line seems to cause problems.
// Convert the other letters to lowercase if they aren't already.
for(int i = 1; name[i] != '\0'; i++) {
if(islower(name[i])) {
name[i] = tolower(name[i]);
} else {
name[i] = name[i];
}
}
name[i] = '\0';
printf("After: %s", name);
}
void my_caller(*name1) {
printf("Name before changing case: %s\n", name1);
myFunction(name1);
printf("Name after changing case: %s\n", name1);
}
// In another .c file.
int main() {
char name1[] = "adam";
my_caller(&name1);
}
In myFunction, if I comment out the lines except for
name[0] = toupper(name[0]);
I still get the segmentation fault. So that would suggest that this line is (one of) the culprits, but I don't understand why. I want to convert the letter to uppercase and put it back into the string.
To start with, having a function definition like
void my_caller(name1)
is problematic, as missing type (used to be, now obsolete rule) default to int. You want this to be a char *. not int.
You need to change it to
void my_caller(char * name1) {....
Moreover, you need to call the function as my_caller(name1);, passing an array is the same as passing a pointer to the first element of the array.
Also, you don't pass the address of the array (check the types if you're in confusion) while calling the function.
That said, inside myFunction(), the scope of i is limited to the for loop only, but you want to use that beyond the scope (to null-terminate), so you got to declare i in the function block scope.
Moral of the story: Turn up the compiler warning / error settings, and pay close attention to the messages emitted by the compiler. They are there for a reason.
Note: After making these changes, code works as expected.

C - Freshly allocated char* contains existing data

C programming newbie here...
I have a function which does some maths and stores the result in an output variable:
void myFunction(char* output) {
unsigned char myData[64]={0};
// Call to another function which fills the 'myData' array
compute(myData);
// Now let's format the result in our output variable
for (int n=0; n<64; n++) {
sprintf(output, "%s%02x", myData[n]);
}
}
The output char array is allocated by the caller in a variable called result:
void main(void) {
char* result = NULL;
result = malloc(129 * sizeof(unsigned char)); // twice the size of myData + 1 ending byte
myFunction(result);
// process result here
// (...)
free(result);
}
Problem is I always get some garbage stuff at the beginning of result, for instance:
���˶ang/String;8fb5ab60ed2b2c06fa43d[...]
Here the expected data starts at 8fb5ab60ed2b2c06fa43d. After doing some logs, I know that result already contains ���˶ang/String; before the sprintf() loop.
I don't understand how this can occur: isn't the malloc() function supposed to reserve memory for my variable? I guess this garbage comes from another memory area, which will eventually lead to some funky behavior...
That said, I've found a workaround just by adding a null ending byte at the 1st position of result, before calling the function:
result[0]='\0'; // initialisation
myFunction(result);
Now it works perfectly but I highly doubt that's good practice... Any advice?
Here's your problem:
for (int n=0; n<64; n++) {
sprintf(output, "%s%02x", myData[n]);
}
Your format specifier to sprintf expects a char * followed by an unsigned int. You're only passing in an unsigned char (which is converted to an int), so this character value is being interpreted as an address. Using the wrong format specifier to sprintf invokes undefined behavior.
It looks like you were attempting to append to output. The way to do that would be to only include the %02x format specifier, then on each loop iteration increment the pointer value output by 2 so that the next write happens in the correct place:
for (int n=0; n<64; n++, output+=2) {
sprintf(output, "%02x", myData[n]);
}

Value was not retained outside of a function

I'm writing a program that should get its inputs from a text file by using input redirection in a function called GetInput. (The text file contains 10 words.) The code should then be able to print the contents of ListWord in the Print function.
This is what I have so far.
I keep on getting errors while trying to run this code. I tried to remove * before ListWord and the code works but it does not retain the word (string) that was stored in it. But removing * before ListWord does not make sense to me. What am I doing wrong?
void GetInput( char** ListWord)
{
int i=0;
char word[30]; //each word may contain 30 letters
*ListWord = malloc(sizeof(char*)*10); //there are 10 words that needs to be allocated
while(scanf("%s", word)==1) //Get Input from file redirection
{
*ListWord[i]= (char *)malloc(30+1);
printf("%s\n", word); //for checking
strcpy(*ListWord[i], word);
printf("%s\n", *ListWord[i]); //for checking
i++;
}
}
void Print(char *ListWord)
{
//print ListWord
int i;
for (i=0; i<10; i++)
{
printf("%s", ListWord[i]);
}
}
int main()
{
char * ListWord;
GetInput(&ListWord);
printf("%s\n", ListWord[0]);
Print(ListWord);
free(ListWord);
return 0;
}
(Note: This is a homework. Thank you and sorry if it's unclear)
Due to *operator precedence the expression *ListWord[i] doesn't do what you think it does. In fact you should be getting errors or warnings from the code you have.
The compiler thinks that *ListWord[i] means *(ListWord[i]), which is not right. You need to use (*ListWord)[i].
Unfortunately that's only the start of your problems. A bigger problem is that the pointer you pass to the function GetInput is not a pointer to what could become an array of strings, but a pointer to a single string.
For a dynamic allocated array of strings, you need a pointer to a pointer to begin with, and then emulate pass-by-reference on that, i.e. you need to become a three star programmer which is something you should avoid.
Instead of trying to pass in the array to be allocated as an argument, have the GetInput return the array instead. Something like
char **GetInput(void)
{
// Allocate ten pointers to char, each initialized to NULL
char **ListWords = calloc(10, sizeof(char *));
if (ListWords == NULL)
return NULL;
char word[31];
for (int i = 0; i < 10 && scanf("%30s", word) == 1; ++i)
{
ListWords[i] = strdup(word);
}
return ListWords;
}
The above code adds some security checks, so you will not go out of bounds of either the temporary array you read into, or the ListWords array. It also makes sure the ListWords array is initialized, so if you read less then 10 words, then the remaining pointers will be NULL.
Of course you need to change your main function accordingly, and also your Print function, because now it only takes a single string as argument, not an array of strings. You also of course need to free every single string in the array because freeing the array.

Delete chars from string C

So i start learning C from a book, and one of the exercises was to create a function that will take 2 string and delete from the first string the characters in the second string.
We stile didn't learn about pointer, so i guess this is possible without them,
but when i try to run my code its crush.
The code:
#include <stdio.h>
#include <string.h>
char squis(char string[], char sub[])
{
int i, c;
char ret_string[strlen(string)];
int map[strlen(string)];
for(i=0; i<= strlen(string);i++)
map[i] = -1;
for(i=0; i<= strlen(sub);i++)
{
while(string[c]!='\0')
{
if (string[c]==sub[i])
map[c] = c;
c++;
}
c=0;
}
for(i=0; i<= strlen(string);i++)
{
if (map[i]==-1)
ret_string[c++] = string[i];
}
ret_string[c] ='\0';
return ret_string[0];
}
int main()
{
char string[] = "string";
char remove[] = "sasas";
printf("%s",squis(string,remove));
return 0;
}
I stile newbie in C, so I think the problem lay on my lack of understanding in the way that C work.
Thanks a lot for help :-)
Update: its seem the problem laying in the return in the end of the function.
The function seems to work well when when i print ret_string inside the function(except one bug that make the function ignore the first char in the sub string, but i will deal with it later), but when i try to return the array to print it in the main function its fail.
There is specific rules for returning array in C?
Here is an obvious problem:
int map[strlen(string)];
for(i=0; i<= strlen(string);i++)
map[i] = -1;
You create an array of strlen(string) characters, and then you initialize strlen(string) + 1 characters in the array. Writing out of bounds of an array leads to undefined behavior, where anything could happen.
Change the loop condition to less-than <. You should probably do it in all your loops.
You have a similar problem with ret_string, which will be the string you return. It's going to be at most strlen(string) characters, but then you need to add one character for the string terminator so the array needs to be strlen(string) + 1 long.
Then you have the problem that the squis function only return a single character but in your printf call you treat this single character as a string. This should make your compiler scream a warning at you. If you fix this by simply returning ret_string you will have another case of undefined behavior, as you then return a pointer to a local variable, which goes out of scope when the function exits, so the returned pointer is no longer valid. And if you decide to allocate ret_string on the heap, with the current call you have a memory leak as then the pointer is not saved so you can free the allocated memory.

Resources