问题
Can someone please explain me why I get "Segmentation fault..." and how to fix it on this bit of code?
#include<stdio.h>
int str_length(char *s) {
int length = 0, i;
for(i = 0; *s; i++) {
s++;
}
return i;
}
char *strdel(char *s, int pos, int n) {
int i;
char *p, str[] = "";
p = str;
for(i = 0; i < str_length(s) - n + 1; i++) {
if(i >= pos) {
*(p + i) = *(s + i + n);
}
else {
*(p + i) = *(s + i);
}
}
s = str;
return s;
}
int main() {
char *str = "abcdef";
printf("str_lengh: %d\n", str_length(str));
printf("strdel: %s\n", strdel(str, 1, 2));
return 0;
}
And I get this output:
str_lengh: 6
strdel: adef
Segmentation fault (core dumped)
Also, is there a better way to create a function: char *strdel(char *s, int pos, int n); that deletes the n characters from position pos than the one I did?
回答1:
I think you are writing all over the stack here...
char *strdel(char *s, int pos, int n) {
int i;
char *p, str[] = "";
p = str; // p points to str which is "" and is on the stack with length 0.
for(i = 0; i < str_length(s) - n + 1; i++) {
if(i >= pos) {
*(p + i) = *(s + i + n); // now you are writing onto the stack past p
}
else {
*(p + i) = *(s + i);// now you are writing onto the stack past p
}
}
s = str; // now s points to space on stack
return s; // now you return a pointer to the stack which is about to disapear
}
Whenever you write past p, which is often, you are running into Undefined Behavior. UB You are writing into space which has not been allocated on the heap or on the stack.
You can write a version of strdel that works only on s. Something like this if I understand strdel right: (roughly, not tested!, needs bounds checking on pos and n )
char *strdel(char *s, int pos, int n) {
char *dst = s + pos, *src = s + pos + n;
while(*src) {
*dst++ = *src++;
}
*dst = 0;
return s;
}
回答2:
I'll throw in my solution for the second part as well. Here's my strdel
char * strdel(char * s, int pos, int n){
memmove(s + pos, s + pos + n, strlen(s) - pos - n + 1);
return s;
}
It doesn't copy, it doesn't do bounds checking and the return-value is rather redundant (as it's equal to the input s
). So all-in-all it's very standard-C-library-like.
Warning! Cannot be used for string-constants as it modifies s
(hence no const char * s
).
回答3:
To address the second part of your question, I would have written it something like this (assuming you're going to be passing in string constants and therefore must make a copy of the incoming string):
/*
* Returns a copy of the NUL terminated string at s, with the
* portion n characters long starting at position pos removed.
*/
char* strdel(char* s, int pos, int n)
{
int size = strlen(s);
char* t = malloc(size - n);
memcpy(t, s, pos);
memmove(t + pos, s + pos + n, size - n + 1);
return t;
}
来源:https://stackoverflow.com/questions/19696338/c-string-pointer-function-strdel