-1

I have a string that I'm iterating through looking for a particular word, which happens to be in-between two white-spaces.

For example:

// where the word that I'm looking for is /docs/index.html
const char* c = "GET /docs/index.html HTTP/1.1\r\n";

I find the word as follows;

const char* wbeg = strchr(c, ' ') + 1; // points to '/'
const char* wend = strchr(wbeg, ' ') -1; // points to 'l'

If I want to store that word into another location, which I implemented using strncpy

char word[256];
strncpy(word, wbeg, wend - wbeg);

I get the following error

Exception thrown at 0x00007FFAAE8C4A74 (ucrtbased.dll) in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x0000000000000000.

Tom11
  • 2,419
  • 8
  • 30
  • 56
Strahinja Ajvaz
  • 2,521
  • 5
  • 23
  • 38
  • Did you check the return of `strchr()` for `NULL`? – EOF May 10 '16 at 12:16
  • `char word[256];` --> `char word[256]="";`, `strncpy(word, wbeg, wend - wbeg);` --> `strncpy(word, wbeg, wend - wbeg + 1);` – BLUEPIXY May 10 '16 at 12:17
  • The code breaks before it executes the function. All I get is that one error. – Strahinja Ajvaz May 10 '16 at 12:18
  • 4
    @stanna: If the code breaks before the function, why don't you post the *relevant* code? – EOF May 10 '16 at 12:20
  • 2
    Time to learn how to use your debugger. – Jabberwocky May 10 '16 at 12:25
  • Please post the FULL code that shows the error. Otherwise we'll be guessing in the blind and you won;t get any wiser either. – Paul Ogilvie May 10 '16 at 12:41
  • You will learn some useful skills by debugging this type of problem for yourself. Simply print out the wbeg, wend, and wend - wbeg values to make sure they are what you expected them to be, and read the library reference for strncpy. – jarmod May 10 '16 at 12:52
  • 1
    Code presented does not error. Certainly it is some use of `word` _after_ `strncpy()` that fails and causes "Access violation writing location 0x0000000000000000". Vote to close as this post lacks "shortest code necessary to reproduce" – chux - Reinstate Monica May 10 '16 at 14:31

2 Answers2

1

strncpy is a crappy function. It doesn't nul terminate strings correctly if source is longer than count parameter:

char s[] = "AAAAA";
strncpy(s, "BB", 2);
// s is now "BBAAA", not "BB"

You need to explicitly terminate the string after copying.

char word[SIZE];
ptrdiff_t count = wend - wbeg + 1;
if(count < SIZE) {
    memcpy(word, wbeg, count); // might as well use memcpy
    word[count] = '\0';
}
else // handle error
user694733
  • 15,208
  • 2
  • 42
  • 68
  • 1
    He says he gets the error when calling strncpy. He doesn't show whether he terminates with zero or not, so you are just guessing. Neither is strncpy "crappy"; it just does as specified. – Paul Ogilvie May 10 '16 at 12:40
  • @PaulOgilvie `strncpy` might do as it's specified, and might have been handy for the purpose it was made for. But is it well named? Is it suitable for general purpose use? Should it been included in standard library? Answers are no, no, and **no**. – user694733 May 10 '16 at 13:03
1

When the essentials you have shown in your post are run in a simple main() program,...

int main()
{
    const char* c = "GET /docs/index.html HTTP/1.1\r\n";
    const char* wbeg = strchr(c, ' ') + 1; // points to '/'
    const char* wend = strchr(wbeg, ' ') -1; // points to 'l'
    char word[256];
    strncpy(word, wbeg, wend - wbeg);

    printf("%s", word);

    return 0;
}

...no faults are observed in my environment. So the only suggestions, short of posting the rest of the relevant code, all center around making sure you are not invoking UB.

1) In your statement:

strncpy(word, wbeg, wend - wbeg);

`wend - wbeg` is == 15

while /docs/index.html is 16 char long.
Change your statement to:

strncpy(word, wbeg, (wend - wbeg)+1);

2) Start with initialized variables:

  char word[SIZE] = ""  

3) strncpy does not NULL terminate. If the target you are copying to has not been initialized prior to use, or you do not explicitly null terminate after using, UB can occur. example:

char target[];  //contents of target are not guaranteed
char source[]="abcdefghijklmnopqrstuv";
strncpy(target, source, 3);

it is possible to get the following results:

|a|b|c|?|?|?|?|?|?|?|?|?|?|?|?|?|...

where ? can be anything.

If you want to guarantee that an ASCII NUL byte is at the end of the copied bytes, you can use the following:

strncpy (target, source, 3);
target[3] = 0;
|a|b|c|\0|?|?|?|?|?|?|?|?|?|?|?|?|...

4) If copying takes place between two objects that overlap, the behavior is undefined. Make sure you are checking the results of strchr() functions before using their results in strncpy()

ryyker
  • 22,849
  • 3
  • 43
  • 87