I'm having trouble storing an integer into an array of strings using sprintf(). I am trying to create a new argv list to pass into my child process. I have 'curr' storing the correct value since I've tested in in GDB. My code is as follows:
我使用sprintf()将整数存储到字符串数组中时遇到问题。我正在尝试创建一个新的argv列表以传递到我的子进程。自从我在GDB中测试以来,我已经'curr'存储了正确的值。我的代码如下:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h> /* for pid_t */
int main(int argc, char *argv[]){
static char *argv2[] = {"./datagen", "10", "outputfile", "SIGUSR1"};
pid_t pid = fork();
int curr = getpid();
sprintf(argv2[4], "%s", curr);
if(pid == 0)
{
printf("You are in the child process.\n");
}
else{
printf("You are in the parent process. Process ID is %d\n", getpid());
}
return;
}
After exhaustively searching around for a clear answer, I have yet to find anything. Ideally, the 4th slot of argv2 will store the process id as a string. However, I am getting a segmentation fault 11. If anyone could shed some light on this issue I would be eternally grateful.
在彻底搜索了一个明确的答案后,我还没有找到任何东西。理想情况下,argv2的第4个插槽会将进程ID存储为字符串。但是,我遇到了分段错误11.如果有人能够对这个问题有所了解,我将永远感激不尽。
Thank you!!
4 个解决方案
#1
4
You can't do that
你不能这样做
static char *argv2[] = {"./datagen", "10", "outputfile", "SIGUSR1"};
is a declaration of an array of char
pointers, which are pointing to string literals, and further more to four string literals only, you can't extend it nor modifiy the strings.
是一个char指针数组的声明,它指向字符串文字,而且只指向四个字符串文字,你不能扩展它,也不能修改字符串。
What you need is
你需要的是什么
char argv2[10][100] = {"./datagen", "10", "outputfile", "SIGUSR1"};
assuming that you want 10
strings of maximum length 100
, which you can obviously change.
假设你想要10个最大长度为100的字符串,你可以明显地改变它。
Also, the format specifier for integers is "%d"
so you have another mistake, having said all that you can now
此外,整数的格式说明符是“%d”,所以你有另一个错误,已经说了所有你现在可以
sprintf(argv2[4], "%d", curr);
and I would suggest the snprintf()
function, since it will avoid buffer overflow problems,
我会建议使用snprintf()函数,因为它可以避免缓冲区溢出问题,
snprintf(argv2[4], sizeof(argv[4]), "%d", curr);
chux comment is correct if you want to have control on whether the specified length of the string was enough, you should check the return value of snprintf()
, in case there wasn't sufficient space to write all the source string into the destination it will be truncated, if snprintf()
returns a value larger or equal to the requested maximum, it means that the string was truncated, so a simple check like
chux注释是正确的如果你想控制字符串的指定长度是否足够,你应该检查snprintf()的返回值,以防没有足够的空间将所有源字符串写入目标它将被截断,如果snprintf()返回一个大于或等于请求的最大值的值,则意味着字符串被截断,所以简单的检查就像
if (snprintf(argv2[4], sizeof(argv[4]), "%d", curr) >= sizeof(argv[4]))
doSomething_TheString_Was_Truncated();
although, for 100
characters and the "%d"
that will not happen, but I firmly believe that people must write safe code as a habit, rather than only checking possible problems, check for every thing that can conceptually go wrong, no matter how unlikely. Because sometimes there will be situations where an unexpected thing will happen.
虽然,100个字符和“%d”不会发生,但我坚信人们必须把安全的代码写成一种习惯,而不是只检查可能出现的问题,检查所有可能在概念上出错的事情,无论如何不太可能。因为有时候会出现意想不到的事情。
Note: as chux pointed out again, snprintf()
will return a negative in case of an error, you can check for that separately, to check if there was an error.
注意:当chux再次指出时,snprintf()将在出现错误时返回负数,您可以单独检查,以检查是否有错误。
#2
1
Simple steps:
1) Determine array size information from existing argv
, argc
arguments.
简单步骤:1)从现有的argv,argc参数确定数组大小信息。
int i, len=0, lenKeep=21;//initialize large enough to contain pid integer
for(i=0;i<argc;i++)
{
len = strlen(argv[i])
if(lenKeep<len)lenKeep = len;
}
2) use that size information to create a new string array, argv2
, with additional elements if necessary. (argv2 will be an array of strings, create sufficient space.)
2)使用该大小信息创建一个新的字符串数组argv2,如果需要,还可以使用其他元素。 (argv2将是一个字符串数组,创建足够的空间。)
char argv2[argc+1][lenKeep+1];
//argc+1 allows for additional array element
//lenKeep+1 provides space for all existing content
3) add new information to the string array in the normal way.
3)以正常方式向字符串数组添加新信息。
sprintf(argv2[argc], "%d", curr); //argv2 array contains argc + 1 elements
//so now argc is a valid index value
#3
0
sprintf(argv2[4], "%s", curr);
breaks the array, which has only 4 elements.
sprintf(argv2 [4],“%s”,curr);打破数组,只有4个元素。
Even if it has more elements, you are writing to a string literal which is Undefined Behaviour.
即使它有更多元素,您也要写入一个字符串文字,即Undefined Behavior。
#4
0
Try using %d instead of %s, it should anyways be saved as a C string.
尝试使用%d而不是%s,它应该保存为C字符串。
#1
4
You can't do that
你不能这样做
static char *argv2[] = {"./datagen", "10", "outputfile", "SIGUSR1"};
is a declaration of an array of char
pointers, which are pointing to string literals, and further more to four string literals only, you can't extend it nor modifiy the strings.
是一个char指针数组的声明,它指向字符串文字,而且只指向四个字符串文字,你不能扩展它,也不能修改字符串。
What you need is
你需要的是什么
char argv2[10][100] = {"./datagen", "10", "outputfile", "SIGUSR1"};
assuming that you want 10
strings of maximum length 100
, which you can obviously change.
假设你想要10个最大长度为100的字符串,你可以明显地改变它。
Also, the format specifier for integers is "%d"
so you have another mistake, having said all that you can now
此外,整数的格式说明符是“%d”,所以你有另一个错误,已经说了所有你现在可以
sprintf(argv2[4], "%d", curr);
and I would suggest the snprintf()
function, since it will avoid buffer overflow problems,
我会建议使用snprintf()函数,因为它可以避免缓冲区溢出问题,
snprintf(argv2[4], sizeof(argv[4]), "%d", curr);
chux comment is correct if you want to have control on whether the specified length of the string was enough, you should check the return value of snprintf()
, in case there wasn't sufficient space to write all the source string into the destination it will be truncated, if snprintf()
returns a value larger or equal to the requested maximum, it means that the string was truncated, so a simple check like
chux注释是正确的如果你想控制字符串的指定长度是否足够,你应该检查snprintf()的返回值,以防没有足够的空间将所有源字符串写入目标它将被截断,如果snprintf()返回一个大于或等于请求的最大值的值,则意味着字符串被截断,所以简单的检查就像
if (snprintf(argv2[4], sizeof(argv[4]), "%d", curr) >= sizeof(argv[4]))
doSomething_TheString_Was_Truncated();
although, for 100
characters and the "%d"
that will not happen, but I firmly believe that people must write safe code as a habit, rather than only checking possible problems, check for every thing that can conceptually go wrong, no matter how unlikely. Because sometimes there will be situations where an unexpected thing will happen.
虽然,100个字符和“%d”不会发生,但我坚信人们必须把安全的代码写成一种习惯,而不是只检查可能出现的问题,检查所有可能在概念上出错的事情,无论如何不太可能。因为有时候会出现意想不到的事情。
Note: as chux pointed out again, snprintf()
will return a negative in case of an error, you can check for that separately, to check if there was an error.
注意:当chux再次指出时,snprintf()将在出现错误时返回负数,您可以单独检查,以检查是否有错误。
#2
1
Simple steps:
1) Determine array size information from existing argv
, argc
arguments.
简单步骤:1)从现有的argv,argc参数确定数组大小信息。
int i, len=0, lenKeep=21;//initialize large enough to contain pid integer
for(i=0;i<argc;i++)
{
len = strlen(argv[i])
if(lenKeep<len)lenKeep = len;
}
2) use that size information to create a new string array, argv2
, with additional elements if necessary. (argv2 will be an array of strings, create sufficient space.)
2)使用该大小信息创建一个新的字符串数组argv2,如果需要,还可以使用其他元素。 (argv2将是一个字符串数组,创建足够的空间。)
char argv2[argc+1][lenKeep+1];
//argc+1 allows for additional array element
//lenKeep+1 provides space for all existing content
3) add new information to the string array in the normal way.
3)以正常方式向字符串数组添加新信息。
sprintf(argv2[argc], "%d", curr); //argv2 array contains argc + 1 elements
//so now argc is a valid index value
#3
0
sprintf(argv2[4], "%s", curr);
breaks the array, which has only 4 elements.
sprintf(argv2 [4],“%s”,curr);打破数组,只有4个元素。
Even if it has more elements, you are writing to a string literal which is Undefined Behaviour.
即使它有更多元素,您也要写入一个字符串文字,即Undefined Behavior。
#4
0
Try using %d instead of %s, it should anyways be saved as a C string.
尝试使用%d而不是%s,它应该保存为C字符串。