strcat implementation?

K

Kevin C.

Never mind my last post about pointer subtraction, I traced the code and
found the offender to be strcat.

char call[] = "del ";
system(strcat(strcat(call, del->table_name), ".tab"));

After this line, trying to dereference del results in page faults or
garbage. This makes me wonder how strcat is implemented, in terms of what it
actually does with the arguments. Seems like it actually moves the pointer.
Anyone know?
 
R

Robert Harris

Kevin said:
Never mind my last post about pointer subtraction, I traced the code and
found the offender to be strcat.

char call[] = "del ";
system(strcat(strcat(call, del->table_name), ".tab"));
You have declared call[] as an array of 5 chars; your strcat call has
written beyond the array so anything is possible.
 
T

tom_usenet

Never mind my last post about pointer subtraction, I traced the code and
found the offender to be strcat.

char call[] = "del ";
system(strcat(strcat(call, del->table_name), ".tab"));

After this line, trying to dereference del results in page faults or
garbage. This makes me wonder how strcat is implemented, in terms of what it
actually does with the arguments. Seems like it actually moves the pointer.
Anyone know?

In addition to the other comments, if you don't know much about
pointers and arrays (and it seems you don't), then you might find it
easier to use the string class from the <string> header. e.g.

std::string call = "del ";
call += del->table_name;
call += ".tab";

There are no memory management issues to be concerned with with
std::string - it handles its own memory allocation, freeing the memory
when the string goes out of scope. That will be slower than the array
approach, but this is only a concern in a tight inner loop generally.

Tom
 
D

David Resnick

Kevin C. said:
Never mind my last post about pointer subtraction, I traced the code and
found the offender to be strcat.

char call[] = "del ";
system(strcat(strcat(call, del->table_name), ".tab"));

After this line, trying to dereference del results in page faults or
garbage. This makes me wonder how strcat is implemented, in terms of what it
actually does with the arguments. Seems like it actually moves the pointer.
Anyone know?

The array call is allocated 5 bytes above ('d' 'e' 'l' ' ' '\0'). Any
attempt
to call strcat with it as the target will overwrite its array
boundries, unless you are attempting to append the empty string.

You could try to fix this as a hack by having
char call[100] = "del ";
Assuming that 100 will always hold what you need. Sadly, such
assumptions turn out to be right only until they are not. Maybe the
assumption was right when the code was written, etc. The correct way
to fix it is to figure out how much room you need for the 3 strings
you are putting together (not forgetting to add 1 for the terminating
NUL), dynamically allocate it, put it all together, and
issue your system command.

const char *fmt = "del %s.tab";
/* allocates 1 byte more than needed. whatever */
char *syscmd = malloc(strlen(fmt) + strlen(del->table_name) + 1);

if (syscmd == NULL) {
exit(EXIT_FAILURE);
}
else {
sprintf(syscmd, fmt, del->table_name);
system(syscmd);
free(syscmd);
}
 
D

Darrell Grainger

Never mind my last post about pointer subtraction, I traced the code and
found the offender to be strcat.

char call[] = "del ";
system(strcat(strcat(call, del->table_name), ".tab"));

After this line, trying to dereference del results in page faults or
garbage. This makes me wonder how strcat is implemented, in terms of what it
actually does with the arguments. Seems like it actually moves the pointer.
Anyone know?

You are over-thinking this. Just read the definition of strcat. You have
declared the array call to be 5 characters long. The function strcat will
store everything in the call array. If the resulting string is greater
than 5 characters (and it is) then you are going to have undefined
behaviour. This is true for 100% of the implementations of strcat. You
don't need to know how your compiler has implemented strcat to know this.

Try:

char *call;
char tmp1[] = "del ";
char tmp2[] = ".tab";
int len = sizeof tmp1 + sizeof tmp2 + strlen(del->table_name);

if((call = malloc(len)) == NULL) exit(EXIT_FAILURE);
sprintf(call, "%s%s%s", tmp1, del->table_name, tmp2);
system(call);
 
R

Ross Kendall Axe

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

tom_usenet wrote:
|
|
|>Never mind my last post about pointer subtraction, I traced the code and
|>found the offender to be strcat.
|>
|>char call[] = "del ";
|>system(strcat(strcat(call, del->table_name), ".tab"));
|>
|>After this line, trying to dereference del results in page faults or
|>garbage. This makes me wonder how strcat is implemented, in terms of
what it
|>actually does with the arguments. Seems like it actually moves the
pointer.
|>Anyone know?
|
|
| In addition to the other comments, if you don't know much about
| pointers and arrays (and it seems you don't), then you might find it
| easier to use the string class from the <string> header. e.g.
|
| std::string call = "del ";
| call += del->table_name;
| call += ".tab";
|
| There are no memory management issues to be concerned with with
| std::string - it handles its own memory allocation, freeing the memory
| when the string goes out of scope. That will be slower than the array
| approach, but this is only a concern in a tight inner loop generally.
|
| Tom

Ummmm, doesn't work in C.

Ross
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFAm6q99bR4xmappRARAgI9AKCW55sbN5ZHcETo4DE7tON7mp9uwACfQJ2/
KhsDGc+zvbyMtNboClOiRf8=
=bdRS
-----END PGP SIGNATURE-----
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,818
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top