Problem with Sprintf


 
Thread Tools Search this Thread
Top Forums Programming Problem with Sprintf
# 1  
Old 10-20-2010
Power Problem with Sprintf

Hi,

I have the below sample code to hash the input number read from file. File will have 16 to 19 digit number and executable hash the number using some logic and returns the hashed value. Each digit in the 16 digit number is converted to a 4 byte value. That if the input is 16digit integer, the output is 64byte string. I have split the code in to two. One main function and other file having this hashing function as shown below:

MAIN:
Code:

ganesh@ubuntu:~/my_programs/c$ cat main.c
# include "fnhash.h"
# include <stdio.h>

int main(int argc, char *argv[])
{
	if(argc!=2)
	{
		printf("Usage wrong");
		exit(1);
	}

	FILE *fp;
	if((fp=fopen(argv[1],"r"))==NULL)
	{
		printf("File opening error\n");
		exit(1);
	}

	char *instr;
	char hashnum[100];

	while(!feof(fp))
	{
		while(fscanf(fp,"%s",instr)>0)
		{
			printf("in Number Length : %lu\n",strlen(instr));
			instr[strlen(instr)+1]='\0';
			printf("in Number = %s\n",instr);
			fnhash(instr,hashnum);
			printf("in number : %s\tHashed value : %s\n",instr,hashnum);
		}
	}

	return 0;
}

FUNCTION:
Code:
ganesh@ubuntu:~/my_programs/c$ cat fnhash.c
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "fnhash.h"

void fnhash(const char nbr[],char hsh[])
{
	char *tmpnbr, *tmphsh;
	tmpnbr=nbr;
	tmphsh=hsh;
	char a;
	char b;
	while(*tmpnbr!='\0')
	{
		a=('A'-*tmpnbr)+'A';
		b=('z'+*tmpnbr)-'A';
		sprintf(tmphsh,"%d%c%c",*tmpnbr,a,b);
		tmpnbr++;
		tmphsh=tmphsh+4;
	}
	printf("strlen of hashed value = %lu\n",strlen(hsh));
	tmphsh[strlen(tmphsh)+1]='\0';
	return;
}

The file having the numbers is as below:
Code:
ganesh@ubuntu:~/my_programs/c$ cat numbers.lst
1234567890123456
12345678901234567
1234567890123456789
123456

Execution Step as follows:

Code:
ganesh@ubuntu:~/my_programs/c$ make -f hashmake
gcc -Wall -g -c main.c
main.c: In function ‘main':
main.c:9: warning: implicit declaration of function ‘exit'
main.c:9: warning: incompatible implicit declaration of built-in function ‘exit'
main.c:16: warning: incompatible implicit declaration of built-in function ‘exit'
main.c:26: warning: implicit declaration of function ‘strlen'
main.c:26: warning: incompatible implicit declaration of built-in function ‘strlen'
main.c:26: warning: ‘instr' may be used uninitialized in this function
gcc -Wall -g main.o fnhash.o -o main

ganesh@ubuntu:~/my_programs/c$ ./main numbers.lst
in Number Length : 16
in Number = 1234567890123456
Segmentation fault (core dumped)

On Analysis with GDB,

Code:
ganesh@ubuntu:~/my_programs/c$ gdb main core
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/ganesh/my_programs/c/main...done.
[New Thread 3605]

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `0645Uf49Qj49Qj56Jq'.
Program terminated with signal 11, Segmentation fault.
#0  0x00007f578f8fbb87 in vsprintf () from /lib/libc.so.6

What is the possible reason for this error?? Where Am I going wrong??

Thanks,
Ramkrix

Last edited by Scott; 10-20-2010 at 05:26 PM..
# 2  
Old 10-20-2010
Well, vsprintf, not sprintf, and the code for vsprintf is not here. As I recall, vsprintf is very sensitive to proper usage! (I had a problem with one old Sun compiler inlining away call that generated the stack that had my vsprintf arguments!) Being a 64 bit compile adds another factor I am not sure of, but hopefully everyone is in agreement about the size of stack frames. You might add the includes and code changes to make the warnings go away.

Your sprintf says %d but you give a char* not an int.
# 3  
Old 10-20-2010
Code:
char *instr;

I think you made it a pointer type since the functions said they needed a pointer, but you only got half the idea. sprintf and fnhash take pointers which point to what memory you want them to use. The memory doesn't create itself, so all you're giving them is a pointer to nothing. the commands mindlessly obey the command to write to invalid memory and cause a segmentation fault, hence why the crash is there despite the bug being far earlier.

Code:
char instr[100];

This way when you pass 'instr' it will point to the 100 bytes of space it's defined as. Be careful not to go beyond it.
# 4  
Old 10-20-2010
PS: I usually pass 'char *x' not 'char x[]' as it is more truthful and you should not be moving arrays by value!

For instance, int main( int args, char **argv ) says what is in memory on the stack. argv is a pointer needing double dereferencing to find a character. We better hope that the first dereference gives us (argv points to) an array of char* somewhere in memory. Actually, argc is derived from the count of elements in that array up to the first null (0) pointer, see "man 2 exec", so it will be argc+1 elements long. The caller, lets say exec(), created it before it called main(). The pointers in that array point to additional areas where the null terminated strings of the arguments passed to exec() are stored. So, for a command with 3 arguments, there are 6 memory areas in play: 4 strings, a char * array of 5 pointers, and a stack frame of, for 32 bit code, an int and a pointer (to a pointer to a character). The stack frame is created by the call, but all the rest had to be provided by code: allocated (malloc or declare) and loaded with pointers, data bytes and nulls.

If you are in a hurry, calloc() does the multiply, of size and count, and clearing to nulls = zeroes for you.
# 5  
Old 10-20-2010
Quote:
Originally Posted by DGPickett
PS: I usually pass 'char *x' not 'char x[]' as it is more truthful and you should not be moving arrays by value!
It's passed by reference either way.
Code:
#include <stdio.h>

void function(char arr[60])
{
        printf("arr=%p\n", arr);
}

int main(void)
{
        char buf[60];

        printf("buf=%p\n", buf);
        function(buf);
}

Code:
 $ ./a.out
buf=0xbf8d06c8
arr=0xbf8d06c8
$

All giving a function parameter an array type does is stop code in the function from modifying the pointer value. Considering making a pointer copy they can modify is the first thing done in this function though, they might as well make it a pointer and be done with it.
# 6  
Old 10-21-2010
Thank you Corona and DGpicket. As mentioned, I allocated instr with instr[100] and it workd now.. Thank youSmilie

---------- Post updated at 11:12 AM ---------- Previous update was at 11:08 AM ----------

One more question. How to eliminate the warnings here? I have included all necessary header files in "fnhash.c" and the below is my makefile:


Code:
ganesh@ubuntu:~/my_programs/c$ cat hashmake
main : main.o fnhash.o
	gcc -Wall -g main.o fnhash.o -o main
main.o : fnhash.h main.c
	gcc -Wall -g -c main.c
fnhash.o : fnhash.c fnhash.h
	gcc -Wall -g -c fnhash.c

However I'm getting those warnings.
Thanks,
Ramkrix
# 7  
Old 10-21-2010
Yes, never lie to yourself, especially! Smilie

Quote:
Originally Posted by Corona688
It's passed by reference either way.
Code:
#include <stdio.h>

void function(char arr[60])
{
        printf("arr=%p\n", arr);
}

int main(void)
{
        char buf[60];

        printf("buf=%p\n", buf);
        function(buf);
}

Code:
 $ ./a.out
buf=0xbf8d06c8
arr=0xbf8d06c8
$

All giving a function parameter an array type does is stop code in the function from modifying the pointer value. Considering making a pointer copy they can modify is the first thing done in this function though, they might as well make it a pointer and be done with it.


---------- Post updated at 09:27 AM ---------- Previous update was at 09:09 AM ----------




Type warnings:

You should match your subroutines to prototypes, usually by using the #include lines in man 2 xxx, or for main, explicitly say it returns int. For instance, with #include <strings.h>, strchr() is know to return char* not the default int, which is a type violation.

For your own subroutines, prototype them up top, if linked in your own #include "my_include_make_dir_or_minus_I_dir_relative_path_to_file". If they are in this file, you can use my favorite PASCAL cheat: declare/define them above main() or above wherever they are called, so you do not have to sync the prototype to any argument mods.

Remember boolean is int, so for instance, when you check to ensure your malloc succeeded:
Code:
if ( !(cptr=malloc(...)))

should be:
Code:
if ( !(int)(cptr=malloc(...)))

or:
Code:
if ((char*)NULL != (cptr=malloc(...)))

(I like putting the smaller and more constant operand on the left for easy reading.)


Quote:
Originally Posted by ramkrix
Thank you Corona and DGpicket. As mentioned, I allocated instr with instr[100] and it workd now.. Thank youSmilie

---------- Post updated at 11:12 AM ---------- Previous update was at 11:08 AM ----------

One more question. How to eliminate the warnings here? I have included all necessary header files in "fnhash.c" and the below is my makefile:


Code:
ganesh@ubuntu:~/my_programs/c$ cat hashmake
main : main.o fnhash.o
    gcc -Wall -g main.o fnhash.o -o main
main.o : fnhash.h main.c
    gcc -Wall -g -c main.c
fnhash.o : fnhash.c fnhash.h
    gcc -Wall -g -c fnhash.c

However I'm getting those warnings.
Thanks,
Ramkrix

For instance, my "man 2 exit" says exit() needs: #include <stdlib.h>
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. UNIX for Dummies Questions & Answers

Join with awk using sprintf

Hi, Trying to join 2 files with awk (file1 has variable number of fields; file 2 has constant number of fields) file1: hook1|AA|BB|CC|DD hook2|EE|FF file2: hook1|11|22 hook2|33|44 hook3|55|66 output: hook1|11|22|AA|BB|CC|DD hook2|33|44|EE|FF hook3|55|66 What I tried so far:... (3 Replies)
Discussion started by: beca123456
3 Replies

2. Programming

How to right pad with zeros using sprintf?

I need to right-pad with zeros a string by using (s)printf. I looked up the manual and tried with printf("%-19s", buffer); which right-pad the string with spaces. So I tried printf("%019s", buffer); which left-pad the string with zeros. So I tried both printf("%-019s", buffer);... (9 Replies)
Discussion started by: emitrax
9 Replies

3. Shell Programming and Scripting

Problem with awk awk: program limit exceeded: sprintf buffer size=1020

Hi I have many problems with a script. I have a script that formats a text file but always prints the same error when i try to execute it The code is that: { if (NF==17){ print $0 }else{ fields=NF; all=$0; while... (2 Replies)
Discussion started by: fate
2 Replies

4. Shell Programming and Scripting

Detect sprintf and fprintf bad use

Hello again, I don't know about regexp so I throw this question here: How can I detect files where, for example: sprintf (var1, "hello %s %s", sub1); The problem here is that we have 2 %s and only a variable. Or... the inverse: sprintf (var1, "hello %s %s", sub1, sub2, sub3,...subn); ... (2 Replies)
Discussion started by: albertogarcia
2 Replies

5. Shell Programming and Scripting

printf vs sprintf - perl

I would like to assign the output of printf to a variable in perl , it give me back a "1" instead of the time. How can I stuff the variable with what printf returns? Here is my code: #!/usr/bin/perl $time = localtime(time);... (3 Replies)
Discussion started by: Dabheeruz
3 Replies

6. Shell Programming and Scripting

sprintf result on perl

Hello, In perl lang, I have create a string (@str) by sprintf but unfortunately when program printed it out, only I could saw a number like 1. Certainly printf doesn't problem. How I can convert a string that are result of sprintf to a common string format??! Thanks in advance. PLEASE HELP ME. (2 Replies)
Discussion started by: Zaxon
2 Replies

7. Programming

equivalent of sprintf in C++

Hi My requirement is to convert the following to C++ char buffer; sprintf(buffer,"%s %-50s %6s %-6d %s\n",a.substr(0,5),a.substr(10,20)) Since the buffer is of varying length, i cannot hardcode the value as 90. i would like to convert the buffer to string object so that it can receive any... (1 Reply)
Discussion started by: dhanamurthy
1 Replies

8. Shell Programming and Scripting

ksh scripting sprintf

is there any sprintf function in korn shell scripting, or anything similar to sprintf? (2 Replies)
Discussion started by: gfhgfnhhn
2 Replies

9. Programming

sprintf function

Hi, Can someone help me to figure out whether this code is to write file to /tmp/TIMECLOCK directory or just to asign a variable with "/tmp/TIMECLOCK/name.log_copy.pid" as the string? I am looking into an old C program and could not figure out where in the code that creates... (1 Reply)
Discussion started by: whatisthis
1 Replies

10. Solaris

problem with sprintf snprintf in Solaris

******************************** Following is not the real issue. The issue is with popen. Plz continue forward with the thread to get a better picture. ******************************** Hi, I am working on a customised ftp application. In it we have used sprintf to store a UNIX command... (7 Replies)
Discussion started by: diganta
7 Replies
Login or Register to Ask a Question