LinuxQuestions.org
Review your favorite Linux distribution.
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 07-14-2024, 09:02 AM   #1
schneidz
LQ Guru
 
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,326

Rep: Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919
c: segfault while trying to assign a character to an element of a string.


i am essentially trying to remove \n from a string (if it exists).

Code:
1:#include <stdio.h>
2:#include <string.h>
3:#include <stdlib.h>
4:
5:int main(int argc, char *argv[])
6:{
7:  char *ex1 = "123 hello world\n";
8:  char *pp;
9:  int i1;
10:
11:  i1= strtol(ex1, &pp, 10);
12:  printf("ex1 = %s: i1 = %d -- pp = \"%s\" -- strcspn-pp = %d\n",ex1,i1,pp,strcspn(pp,"\n"));
13://  pp[strcspn(pp, "\n")] = '\0';
14:  pp[6] = 'a';
15:  printf("\n\n-----apres call: pp = \"%s\"\n\n\n", pp);
16:}
Code:
~ $ gcc storage/shared/stuff/schneidz-test.c && ./a.out
ex1 = 123 hello world
: i1 = 123 -- pp = " hello world
" -- strcspn-pp = 12
Segmentation fault
if i comment out line 14 it will print the same pp as in line 12.

Last edited by schneidz; 07-14-2024 at 09:08 AM.
 
Old 07-14-2024, 09:19 AM   #2
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,702

Rep: Reputation: 7535Reputation: 7535Reputation: 7535Reputation: 7535Reputation: 7535Reputation: 7535Reputation: 7535Reputation: 7535Reputation: 7535Reputation: 7535Reputation: 7535
your variable pp points to nowhere.
 
Old 07-14-2024, 10:52 AM   #3
schneidz
LQ Guru
 
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,326

Original Poster
Rep: Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919
Quote:
Originally Posted by pan64 View Post
your variable pp points to nowhere.
?
the 2nd parameter of strtol is supposed to store the start of the next chunk after the return.
Code:
pp = " hello world
"

Last edited by schneidz; 07-14-2024 at 10:54 AM.
 
Old 07-14-2024, 10:59 AM   #4
intestinal fortitude
LQ Newbie
 
Registered: Jan 2014
Posts: 17

Rep: Reputation: Disabled
Your problem is that even though ex1 is of type 'char *', the data is it is pointing to is 'const char *' (i.e. it is read-only). Since 'pp' is populated from a pointer into ex1, 'pp' is also pointing to a read-only string.

When you try to assign a value to the character pointed to by pp, you get undefined behavior. In this case, a segfault.

To fix your problem, change the definition of ex1:
char ex1[] = "123 hello world\n";

Quote:
your variable pp points to nowhere.
The call to strtol() puts a valid address into 'pp'.
 
4 members found this post helpful.
Old 07-14-2024, 11:07 AM   #5
intestinal fortitude
LQ Newbie
 
Registered: Jan 2014
Posts: 17

Rep: Reputation: Disabled
Quote:
Originally Posted by schneidz View Post
?
the 2nd parameter of strtol is supposed to store the start of the next chunk after the return.
Code:
pp = " hello world
"
It will have the position where strotol() stopped converting data. In your example, that is the space character after "123".

When I have a string and I want to remove a newline from the end of the string (and only at the end of the string):

Code:
char my_string[] = "This is a test\n";
size_t l;

l = strlen(my_string);
if (l > 0 && my_string[l-1]=='\n')
    my_string[--l] = 0;

Last edited by intestinal fortitude; 07-14-2024 at 11:23 AM.
 
1 members found this post helpful.
Old 07-14-2024, 12:47 PM   #6
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
Blog Entries: 1

Rep: Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886
At compilation use options `-Wall -W -Werror`
 
Old 07-14-2024, 02:00 PM   #7
teckk
LQ Guru
 
Registered: Oct 2004
Distribution: Arch
Posts: 5,218
Blog Entries: 6

Rep: Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874Reputation: 1874
Quote:
i am essentially trying to remove \n from a string (if it exists).
Code:
#include <stdio.h>
#include <string.h>

char* deleteCharC(char* s, char ch) {
    int i, j;
    int len = strlen(s);
    for (i = j = 0; i < len; i++) {
        if (s[i] != ch) {
            s[j++] = s[i];
        }
    }
    s[j] = '\0';
    return s;
}

int main() {
    char ch = '\n';
    
    char a[] = "123 hello world\n";
    printf("%s\n", deleteCharC(a, ch));
    
    char b[] = "456 hello world\n\n\n";
    printf("%s\n", deleteCharC(b, ch));

    char c[] = "789 hello world";
    printf("%s\n", deleteCharC(c, ch));
    
    return 0;
}

//gcc rstring.c -o rstring
Code:
gcc rstring.c -o rstring
./rstring
123 hello world
456 hello world
789 hello world
 
1 members found this post helpful.
Old 07-14-2024, 02:38 PM   #8
schneidz
LQ Guru
 
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,326

Original Poster
Rep: Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919Reputation: 919
Quote:
Originally Posted by NevemTeve View Post
At compilation use options `-Wall -W -Werror`
f.y.i.:
Code:
~ $ gcc -Wall -W -Werror storage/shared/stuff/schneidz-test.c
storage/shared/stuff/schneidz-test.c:12:76: error: format specifies type 'int' but the argument has type 'unsigned long' [-Werror,-Wformat]
   12 |   printf("ex1 = %s: i1 = %d -- pp = \"%s\" -- strcspn-pp = %d\n",ex1,i1,pp,strcspn(pp,"\n"));
      |                                                            ~~              ^~~~~~~~~~~~~~~~
      |                                                            %lu
storage/shared/stuff/schneidz-test.c:5:14: error: unused parameter 'argc' [-Werror,-Wunused-parameter]
    5 | int main(int argc, char *argv[])
      |              ^
storage/shared/stuff/schneidz-test.c:5:26: error: unused parameter 'argv' [-Werror,-Wunused-parameter]
    5 | int main(int argc, char *argv[])
      |                          ^
3 errors generated.

Last edited by schneidz; 07-14-2024 at 02:48 PM.
 
Old 07-14-2024, 11:46 PM   #9
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
Blog Entries: 1

Rep: Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886
That's it. Now you only have to fix every errors.
E.g. for `argc` unused put this line into main:
Code:
(void)argc;
Also the first version of the program had this line:
Code:
char *ex1 = "123 hello world\n";
With the said options the compiler explains the problem clearly: assigning a const pointer to a nonconst pointer-variable.

Last edited by NevemTeve; 07-14-2024 at 11:53 PM.
 
1 members found this post helpful.
Old 07-15-2024, 06:05 AM   #10
intestinal fortitude
LQ Newbie
 
Registered: Jan 2014
Posts: 17

Rep: Reputation: Disabled
GCC with '-Wall' and '-Wall -Wextra' did not give a warning about the constant string. To get a warning about the string, they have to use '-Wwrite-strings'

ETA: I am using Slackware with GCC 14.1.0

Last edited by intestinal fortitude; 07-15-2024 at 06:08 AM.
 
2 members found this post helpful.
Old 07-15-2024, 06:29 AM   #11
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
Blog Entries: 1

Rep: Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886Reputation: 1886
Oh, you are right, the compiler ignores this problem, unless you use yet another option:
Code:
$ gcc schneidz.c -W -Wall -Wwrite-strings -Werror -o schneidz && ./schneidz
schneidz.c: In function ‘main’:
schneidz.c:7:15: error: initialization discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
    7 |   char *ex1 = "123 hello world\n";
      |               ^~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
Edit: Compiling as C++ also works:
Code:
$ g++ schneidz.c
schneidz.c: In function ‘int main(int, char**)’:
schneidz.c:7:15: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
    7 |   char *ex1 = "123 hello world\n";
      |               ^~~~~~~~~~~~~~~~~~~

Last edited by NevemTeve; 07-16-2024 at 03:08 AM.
 
  


Reply

Tags
newlines, segfault


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
[SOLVED] [bash][sed] replace string after fixed string/character? czezz Programming 4 02-15-2022 01:35 PM
[SOLVED] bash split array and assign a variable to an element eamesj Programming 3 03-02-2013 12:19 PM
[SOLVED] copy string a to string b and change string b with toupper() and count the chars beep3r Programming 3 10-22-2010 07:22 PM
[C++] struct.string vs. string. Segfault caused. xtothat Programming 7 03-20-2009 05:27 AM
How do you assign an html element as a php variable? 3vra Programming 1 02-06-2009 05:51 PM

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

All times are GMT -5. The time now is 04:17 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