File name gets truncated

J

jza

I once had a program which would get a directory name in argv[1] and append
"/thumbmap.txt" after it. I couldn't get it to work because when defining some
variables there would appear some garbage in the file name. Already made a
workaround for it, but I still wonder why this does not work as expected.

So, in the following code if I do not define variables cellx .. cgy the program
works fine, but with them defined the file name gets messed up. I wonder why?
Tested under Linux with gcc.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
char*tmap;
char*thumbmap;
char*themos;
char*small;
char*sortedf;
unsigned long*matrix;
unsigned long long tmaplen;
unsigned long long gopointer;
int mosx,mosy;
unsigned int cellx,celly;
unsigned int smallx,smally;
unsigned int cgx,cgy;
unsigned long cgt;
char sortedfb[23];
unsigned char sortedlen=0;
char sortedserial[9];
unsigned int ddlen=0;
FILE*th;

tmap=(char*)malloc(strnlen(argv[1])+14);
if(tmap==NULL){
printf("Out of memory.\n");
return 1;
}
strcpy(tmap,argv[1]);
strcat(tmap,"/thumbmap.txt");
printf("tmap is %s\n",tmap);
th=fopen(tmap,"r");
if(th==NULL){
printf("Unable to open %s\n",tmap);
return 1;
}
printf("Opened %s\n",tmap);
free(tmap);
fclose(th);
return 0;
}
 
M

Malcolm

jza said:
#include <stdio.h>
#include <string.h>

tmap=(char*)malloc(strnlen(argv[1])+14);
Generally I'm sceptical about the benefits of uncast malloc() (the reason
for casting is to allow compilation under C++). However this example shows
that it is indeed possible to forget to include stdlib.h, and I think this
is the source of your problem.
Lose the cast and you will generate the appropriate compiler warning.
 
C

CBFalconer

jza said:
I once had a program which would get a directory name in argv[1]
and append "/thumbmap.txt" after it. I couldn't get it to work
because when defining some variables there would appear some
garbage in the file name. Already made a workaround for it, but
I still wonder why this does not work as expected.

So, in the following code if I do not define variables cellx ..
cgy the program works fine, but with them defined the file name
gets messed up. I wonder why? Tested under Linux with gcc.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
char*tmap;
char*thumbmap;
char*themos;
char*small;
char*sortedf;
unsigned long*matrix;
unsigned long long tmaplen;
unsigned long long gopointer;
int mosx,mosy;
unsigned int cellx,celly;
unsigned int smallx,smally;
unsigned int cgx,cgy;
unsigned long cgt;
char sortedfb[23];
unsigned char sortedlen=0;
char sortedserial[9];
unsigned int ddlen=0;
FILE*th;

tmap=(char*)malloc(strnlen(argv[1])+14);
^^^^^^^ ^^^^^^^
Don't cast malloc. The cast is hiding your failure to #include
<stdlib.h>, and causing undefined behavior from here on. Also
there is no such function as strnlen().
if(tmap==NULL){
printf("Out of memory.\n");
return 1;

The only values you can return is 0, and if you #include
*> strcpy(tmap,argv[1]);
strcat(tmap,"/thumbmap.txt");
printf("tmap is %s\n",tmap);
th=fopen(tmap,"r");
if(th==NULL){
printf("Unable to open %s\n",tmap);
return 1;

Same comment as above.
}
printf("Opened %s\n",tmap);
free(tmap);
fclose(th);
return 0;
}

You also have a herd of unused variable declarations cluttering
things up to no purpose, and apparently don't know that the blank
shortage is over. It is quite permissable to make your statements
legible with judicious blanks.
 
M

Martin Dickopp

CBFalconer said:
The only values you can return [from the `main' function]
is 0, and if you #include <stdlib.h> you can also use EXIT_SUCCESS and
EXIT_FAILURE. Anything else is UB.

<nitpick>
Actually, it's implementation-defined behavior: see 7.20.4.3#5.
</nitpick>

Martin
 
S

Stephen Sprunk

CBFalconer said:
jza said:
I once had a program which would get a directory name in argv[1]
and append "/thumbmap.txt" after it. I couldn't get it to work
because when defining some variables there would appear some
garbage in the file name. Already made a workaround for it, but
I still wonder why this does not work as expected.

Sounds like you're doing something that messes up the stack.
tmap=(char*)malloc(strnlen(argv[1])+14);
^^^^^^^ ^^^^^^^
... Also there is no such function as strnlen().

Not in standard C, but some implementations (such as the OP's GCC on Linux)
may have one. The problem here is that strnlen should take two arguments
and the OP only passes one, which may be where his stack problem comes from.

FWIW, I tested this code with glibc 2.1.3 and egcs-2.91.66 and didn't get
any corruption (with or without changing strnlen to strlen).

S
 
J

Joe Wright

jza said:
I once had a program which would get a directory name in argv[1] and append
"/thumbmap.txt" after it. I couldn't get it to work because when defining some
variables there would appear some garbage in the file name. Already made a
workaround for it, but I still wonder why this does not work as expected.

So, in the following code if I do not define variables cellx .. cgy the program
works fine, but with them defined the file name gets messed up. I wonder why?
Tested under Linux with gcc.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
char*tmap;
char*thumbmap;
char*themos;
char*small;
char*sortedf;
unsigned long*matrix;
unsigned long long tmaplen;
unsigned long long gopointer;
int mosx,mosy;
unsigned int cellx,celly;
unsigned int smallx,smally;
unsigned int cgx,cgy;
unsigned long cgt;
char sortedfb[23];
unsigned char sortedlen=0;
char sortedserial[9];
unsigned int ddlen=0;
FILE*th;

tmap=(char*)malloc(strnlen(argv[1])+14);
if(tmap==NULL){
printf("Out of memory.\n");
return 1;
}
strcpy(tmap,argv[1]);
strcat(tmap,"/thumbmap.txt");
printf("tmap is %s\n",tmap);
th=fopen(tmap,"r");
if(th==NULL){
printf("Unable to open %s\n",tmap);
return 1;
}
printf("Opened %s\n",tmap);
free(tmap);
fclose(th);
return 0;
}
Probably because you abuse malloc() by not #including its
declaration. What is strnlen() ?

/*
In honor of the OP I have named this jza.c
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
char *tmap;
FILE *th;
int ch;
if (argc > 1) {
tmap = malloc(strlen(argv[1]) + 14);
if (tmap == NULL) {
printf("Out of memory.\n");
return EXIT_FAILURE;
}
strcpy(tmap, argv[1]);
strcat(tmap, "/jza.c");
printf("tmap is %s\n", tmap);
th = fopen(tmap, "r");
if (th == NULL) {
printf("Unable to open %s\n", tmap);
return EXIT_FAILURE;
}
printf("Opened %s\n", tmap);
while ((ch = fgetc(th)) != EOF)
putchar(ch);
free(tmap);
fclose(th);
}
return EXIT_SUCCESS;
}

I could pretty it up a lot more, but then it would be my program and
not yours. :)
 
E

Emmanuel Delahaye

In said:
I once had a program which would get a directory name in argv[1] and
append "/thumbmap.txt" after it. I couldn't get it to work because when
defining some variables there would appear some garbage in the file
name. Already made a workaround for it, but I still wonder why this does
not work as expected.

So, in the following code if I do not define variables cellx .. cgy the
program works fine, but with them defined the file name gets messed up.
I wonder why? Tested under Linux with gcc.

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
char*tmap;
char*thumbmap;
char*themos;
char*small;
char*sortedf;
unsigned long*matrix;
unsigned long long tmaplen;
unsigned long long gopointer;
int mosx,mosy;
unsigned int cellx,celly;
unsigned int smallx,smally;
unsigned int cgx,cgy;
unsigned long cgt;
char sortedfb[23];
unsigned char sortedlen=0;
char sortedserial[9];
unsigned int ddlen=0;
FILE*th;

tmap=(char*)malloc(strnlen(argv[1])+14);

Unknown function. You want strlen(). Please don't retype but copy and paste.

Rather than using this evil cast, you'd better provide a prototype for
if(tmap==NULL){
printf("Out of memory.\n");
return 1;
}
strcpy(tmap,argv[1]);
strcat(tmap,"/thumbmap.txt");
printf("tmap is %s\n",tmap);
th=fopen(tmap,"r");
if(th==NULL){
printf("Unable to open %s\n",tmap);
return 1;
}
printf("Opened %s\n",tmap);
free(tmap);
fclose(th);
return 0;
}

You forgot to check argc.

Try again on these new basis:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (int argc, char *argv[])
{
int ret = EXIT_SUCCESS;

if (argc > 1)
{
char *tmap = malloc (strlen (argv[1]) + 14);

if (tmap == NULL)
{
printf ("Out of memory.\n");
ret = EXIT_FAILURE;
}
else
{
strcpy (tmap, argv[1]);
strcat (tmap, "/thumbmap.txt");
printf ("tmap is %s\n", tmap);

{
FILE *th = fopen (tmap, "r");

if (th == NULL)
{
printf ("Unable to open %s\n", tmap);
ret = EXIT_FAILURE;
}
else
{
printf ("Opened %s\n", tmap);
fclose (th);
}
}
free (tmap);
}
}
else
{
printf ("usage xx yyy\n");
ret = EXIT_FAILURE;
}
return ret;
}
 
A

Al Bowers

jza said:
I once had a program which would get a directory name in argv[1] and append
"/thumbmap.txt" after it. I couldn't get it to work because when defining some
variables there would appear some garbage in the file name. Already made a
workaround for it, but I still wonder why this does not work as expected.

So, in the following code if I do not define variables cellx .. cgy the program
works fine, but with them defined the file name gets messed up. I wonder why?
Tested under Linux with gcc.
tmap=(char*)malloc(strnlen(argv[1])+14);
if(tmap==NULL){
printf("Out of memory.\n");
return 1;
}
strcpy(tmap,argv[1]);
strcat(tmap,"/thumbmap.txt");

Maybe they are defining it "\thumbmap.txt"
 
D

Darrell Grainger

I once had a program which would get a directory name in argv[1] and
append "/thumbmap.txt" after it. I couldn't get it to work because when
defining some workaround for it, but I still wonder why this does not
work as expected.

So, in the following code if I do not define variables cellx .. cgy the
program works fine, but with them defined the file name gets messed up.
I wonder why? Tested under Linux with gcc.

#include <stdio.h>
#include <string.h>

You use malloc() and didn't #include said:
int main(int argc, char *argv[]){
char*tmap;
char*thumbmap;
char*themos;
char*small;
char*sortedf;
unsigned long*matrix;
unsigned long long tmaplen;
unsigned long long gopointer;
int mosx,mosy;
unsigned int cellx,celly;
unsigned int smallx,smally;
unsigned int cgx,cgy;
unsigned long cgt;
char sortedfb[23];
unsigned char sortedlen=0;
char sortedserial[9];
unsigned int ddlen=0;
FILE*th;

tmap=(char*)malloc(strnlen(argv[1])+14);

Don't cast the result of malloc(). This is hiding the fact that you did
not have #include <stdlib.h>.

Second, what is strnlen()? Shouldn't that be strlen()?

Third, way +14? If this is for the "/thumbmap.txt" why not use:

const char extra[] = "/thumbmap.txt";
tmap = malloc(strlen(argv[1])+sizeof extra + 1);

Fourth, what if argv[1] does not exist? Check your inputs.
if(tmap==NULL){
printf("Out of memory.\n");
return 1;
}
strcpy(tmap,argv[1]);
strcat(tmap,"/thumbmap.txt");
printf("tmap is %s\n",tmap);

Everything looks good here. I'd make one change:

strcat(tmap, extra);

I also like to use:

printf("tmap is '%s'\n", tmap);

Not important here but it helps spot things like trailing whitespace.
 

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

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top