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 |
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.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
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.
|
|
07-14-2024, 09:02 AM
|
#1
|
LQ Guru
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,326
|
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.
|
|
|
07-14-2024, 09:19 AM
|
#2
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,702
|
your variable pp points to nowhere.
|
|
|
07-14-2024, 10:52 AM
|
#3
|
LQ Guru
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,326
Original Poster
|
Quote:
Originally Posted by pan64
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.
|
|
|
07-14-2024, 10:59 AM
|
#4
|
LQ Newbie
Registered: Jan 2014
Posts: 17
Rep:
|
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.
|
07-14-2024, 11:07 AM
|
#5
|
LQ Newbie
Registered: Jan 2014
Posts: 17
Rep:
|
Quote:
Originally Posted by schneidz
?
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.
|
07-14-2024, 12:47 PM
|
#6
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
|
At compilation use options `-Wall -W -Werror`
|
|
|
07-14-2024, 02:00 PM
|
#7
|
LQ Guru
Registered: Oct 2004
Distribution: Arch
Posts: 5,218
|
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.
|
07-14-2024, 02:38 PM
|
#8
|
LQ Guru
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,326
Original Poster
|
Quote:
Originally Posted by NevemTeve
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.
|
|
|
07-14-2024, 11:46 PM
|
#9
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
|
That's it. Now you only have to fix every errors.
E.g. for `argc` unused put this line into main:
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.
|
07-15-2024, 06:05 AM
|
#10
|
LQ Newbie
Registered: Jan 2014
Posts: 17
Rep:
|
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.
|
07-15-2024, 06:29 AM
|
#11
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
|
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.
|
|
|
All times are GMT -5. The time now is 04:17 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|