Breezeonhold On
Breezeonhold On

Reputation: 25

strncpy Run-time check failure #2 error c++

When I compile and run my program it seems as if everything works fine with the task in hand except I get an " Run-time check failure #2" error. This is my hw assignment by the way and it's my first time trying to use any of the cstring functions so I'm sure that's where I went wrong. Basically I'm appending 2 strings together and I'm almost 100% sure it has something to do with my result parameter getting overrun. Just don't know how to fix it.

#include <iostream>
#include <cstring>
using namespace std;

void concat(const char a[ ], const char b[ ], char result[ ], int result_maxlength);
int main()
{
  char a[] = "Woozle";
  char b[] = "Heffalump";
  char c[5];
  char d[10];
  char e[20];
  concat(a, b, c, 5);
  concat(a, b, d, 10);
  concat(a, b, e, 20);
  cout << c << "\n";
  cout << d << "\n";
  cout << e << "\n";
  return 0;
}
void concat(const char a[ ], const char b[ ], char result[ ], int result_maxlength)
{
strncpy (result,a, result_maxlength);
strncat (result, b, result_maxlength);
result[result_maxlength-1] = '\0';
}

Upvotes: 0

Views: 719

Answers (2)

WhozCraig
WhozCraig

Reputation: 66214

You have several issues with this code that several have pointed out thus far. A very subtle one that few seem to talk about is this: Per the POSIX spec, the behavior of strncpy will NOT set the null-terminator on your string if the number of non-null chars moved reaches the limit specified (the 'n'). It WILL tail-fill nulls to reach 'n', however. Thus:

char ar[3];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0]));

This will end up with a(0) = 'f', a(1) = 'o' and ar(2) = 'o'. There will be no null terminator appended. with the last char ignored It is for this reason people are so minus-1 giddy about invoking this runtime library function. Accounting for this is important. Thus you will often see code like this instead.

char ar[3];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0])-1);
ar[sizeof(ar)/sizeof(ar[0])-1] = 0;

This will likely get what you were really looking for, namely ar = "fo". The plenty-o-space situation reverses this. If you have a buffer with ample room the 'n' will tail-fill with nulls until 'n' is reached if the source string of the copy reaches its own terminator prior to reaching 'n'. Thus:

char ar[30];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0])-1);
ar[sizeof(ar)/sizeof(ar[0])-1] = 0;

Will result in ar = "food" with twenty-six zero-chars following the 'd'. Keeping people on their toes, the not-so-apparent memset-to-zero invoke:

char ar[30];
strncpy(ar, "", sizeof(ar)/sizeof(ar[0]));

Yeah, its just wrong, I know.

All of that being said it should come as no surprise that clearly strncat() behaves differently than your code appears to reflect you may currently believe as well. For example the last parameter does NOT specify the number of chars to limit in the destination. Rather, it describes the number of chars to limit from copying from the source. In other words, as you continue to tack on new strings, that tail space limiter should be continually getting shorter. Of course, to know how much involves keeping track of chars-copied with each step, and as someone pointed out, this makes strncat borderline-useless in many cases, offering up more confusion than utility.

For reference, the precise definitions with defined behavior can be seen here strncpy and strncat. I would highly advise a clear read of both before continuing with your homework.

Upvotes: 1

Ben Voigt
Ben Voigt

Reputation: 283684

strncat is pretty useless, because the num argument is NOT the total size of the destination, it's the number of bytes to copy.

Upvotes: 1

Related Questions