所以我正在尝试一个字符串向量,其中包含我想尝试并使用execve命令运行的参数。我也在复制环境,因为我写的应用程序需要有一个来自进程的传入环境的副本。这个应用程序是用c ++编写的,我收到的错误是#34; Bad Address"来自execve电话。这是我目前的代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <vector>
using namespace std;
int main (int argc, char * argv[], char * envp[]) {
int total = 0;
int a = 0;
int b = 0;
char **my_array;
char **my_envp;
// Setup copy the environment.
while (envp[a] != NULL) {
total++;
a++;
}
my_envp = new char*[total+1];
for (a = 0; a < total; a++) {
my_envp[a] = new char[strlen(envp[a])+1];
strcpy(my_envp[a], envp[a]);
}
a++;
my_envp[a] = NULL;
// Get my path and arguments.
vector<string> random = { "/bin/echo", "Grace ", "Will ", "Dan ", "Scott ", "Kevin ", "Amanda " };
my_array = new char*[random.size()+1];
for (b = 0; b < random.size(); b++) {
my_array[b] = new char[strlen(random[b].c_str())+1];
strcpy(my_array[b], random[b].c_str());
}
b++;
my_array[b] = NULL;
// Run my arguments.
pid_t pid;
pid = fork();
if (pid == 0) {
if (execve(my_array[0], my_array, my_envp) == -1)
perror("");
exit(1);
} else {
waitpid(pid, 0, WUNTRACED);
}
// Clean up time.
for (b = 0; b < random.size(); b++)
delete [] my_array[b];
delete [] my_array;
for (a = 0; a < total; a++)
delete [] my_envp[a];
delete [] my_envp;
return 0;
}
这是我的Valgrind输出:
{"
==27594== Memcheck, a memory error detector
==27594== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==27594== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==27594== Command: ./a.out
==27594==
==27594== Invalid write of size 8
==27594== at 0x40115A: main (in /home/examples/a.out)
==27594== Address 0x5ab6eb0 is 0 bytes after a block of size 560 alloc'd
==27594== at 0x4C2E80F: operator new[](unsigned long) (o)
==27594== by 0x40106E: main (in /home/examples/a.out)
==27594==
==27594== Invalid write of size 8
==27594== at 0x4014E0: main (in /home/examples/a.out)
==27594== Address 0x5ab9220 is 0 bytes after a block of size 64 alloc'd
==27594== at 0x4C2E80F: operator new[](unsigned long) ()
==27594== by 0x4013D1: main (in /home/examples/a.out)
==27594==
==27595== Syscall param execve(argv) points to uninitialised byte(s)
==27595== at 0x549E777: execve (syscall-template.S:84)
==27595== by 0x40151D: main (in /home/examples/a.out)
==27595== Address 0x5ab9218 is 56 bytes inside a block of size 64 alloc'd
==27595== at 0x4C2E80F: operator new[](unsigned long) ()
==27595== by 0x4013D1: main (in /home/examples/a.out)
==27595==
==27595== Syscall param execve(envp) points to uninitialised byte(s)
==27595== at 0x549E777: execve (syscall-template.S:84)
==27595== by 0x40151D: main (in /home/examples/a.out)
==27595== Address 0x5ab6ea8 is 552 bytes inside a block of size 560 alloc'd
==27595== at 0x4C2E80F: operator new[](unsigned long) ()
==27595== by 0x40106E: main (in /home/examples/a.out)
==27595==
Grace Will Dan Scott Kevin Amanda
==27594==
==27594== HEAP SUMMARY:
==27594== in use at exit: 72,704 bytes in 1 blocks
==27594== total heap usage: 80 allocs, 79 frees, 77,249 bytes allocated
==27594==
==27594== LEAK SUMMARY:
==27594== definitely lost: 0 bytes in 0 blocks
==27594== indirectly lost: 0 bytes in 0 blocks
==27594== possibly lost: 0 bytes in 0 blocks
==27594== still reachable: 72,704 bytes in 1 blocks
==27594== suppressed: 0 bytes in 0 blocks
==27594== Reachable blocks (those to which a pointer was found) are not show
==27594== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==27594==
==27594== For counts of detected and suppressed errors, rerun with: -v
==27594== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
"}
我有一种感觉,我创建cstring指针的char指针的方式不正确,或者我遗漏了一些非常明显的东西。感谢。
答案 0 :(得分:2)
您的代码存在问题,既不是您的环境列表也不是
参数列表NULL
终止。然后你从中更新了你的代码
我的建议:
valgrind与之有什么关系?您执行
my_array = new char*[random.size() + 1];
并在制作副本的循环之后执行my_array[b] = NULL
但你做错了错误:
for (a = 0; a < total; a++) {
my_envp[a] = new char[strlen(envp[a])+1];
strcpy(my_envp[a], envp[a]);
}
a++; // <-- does not belong here
my_envp[a] = NULL;
for (b = 0; b < random.size(); b++) {
my_array[b] = new char[strlen(random[b].c_str())+1];
strcpy(my_array[b], random[b].c_str());
}
b++; // <-- does not belong here
my_array[b] = NULL;
和valgrind抱怨说:
==27594== Invalid write of size 8
==27594== at 0x40115A: main (in /home/examples/a.out)
==27594== Address 0x5ab6eb0 is 0 bytes after a block of size 560 alloc'd
==27594== at 0x4C2E80F: operator new[](unsigned long) (o)
==27594== by 0x40106E: main (in /home/examples/a.out)
==27594==
==27594== Invalid write of size 8
==27594== at 0x4014E0: main (in /home/examples/a.out)
==27594== Address 0x5ab9220 is 0 bytes after a block of size 64 alloc'd
==27594== at 0x4C2E80F: operator new[](unsigned long) ()
==27594== by 0x4013D1: main (in /home/examples/a.out)
正确的版本应该是(正如我在评论中写的那样)
for (b = 0; b < random.size(); b++) {
my_array[b] = new char[strlen(random[b].c_str())+1];
strcpy(my_array[b], random[b].c_str());
}
my_array[b] = NULL;
你不需要b++
的原因是因为循环已经在做了。
循环
for(int i = 0; i < 5; ++i)
{
printf("i in loop: %d\n", i);
}
printf("i out of loop\n");
你会得到
i in loop: 0
i in loop: 1
i in loop: 2
i in loop: 3
i in loop: 4
i out of loop: 5
因为当条件计算结果为false时循环结束,并且会发生这种情况
何时i == 5
。如果您增加for
,这同样适用于上面的b
循环
在循环结束后再次增加。
所以让我们说random.size()
是5(就像在我的循环示例中)并且你已经分配了
random.size() + 1 == 6
元素的空间,因此您只能从内存中索引
从0到5.在循环结束时b
为5,如果你再做b++
,那么b
是6和6超出my_array
的范围。
要证明这是我编译的代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <vector>
using namespace std;
int main (int argc, char * argv[], char * envp[]) {
// these variables must be unsigned, vector.size()
// returns an unsigned value
unsigned int total = 0;
unsigned int a = 0;
unsigned int b = 0;
char **my_array;
char **my_envp;
// Setup copy the environment.
while (envp[a] != NULL) {
total++;
a++;
}
my_envp = new char*[total+1];
for (a = 0; a < total; a++) {
my_envp[a] = new char[strlen(envp[a])+1];
strcpy(my_envp[a], envp[a]);
}
my_envp[a] = NULL;
// Get my path and arguments.
vector<string> random = { "/bin/echo", "Grace ", "Will ", "Dan ", "Scott ", "Kevin ", "Amanda " };
my_array = new char*[random.size()+1];
for (b = 0; b < random.size(); b++) {
my_array[b] = new char[strlen(random[b].c_str())+1];
strcpy(my_array[b], random[b].c_str());
}
my_array[b] = NULL;
// Run my arguments.
pid_t pid;
pid = fork();
if (pid == 0) {
if (execve(my_array[0], my_array, my_envp) == -1)
perror("");
exit(1);
} else {
waitpid(pid, 0, WUNTRACED);
}
// Clean up time.
for (b = 0; b < random.size(); b++)
delete [] my_array[b];
delete [] my_array;
for (a = 0; a < total; a++)
delete [] my_envp[a];
delete [] my_envp;
return 0;
}
和输出
$ g++ a.cpp -oa -g -Wall
$ valgrind ./a
==15833== Memcheck, a memory error detector
==15833== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==15833== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==15833== Command: ./a
==15833==
Grace Will Dan Scott Kevin Amanda
==15833==
==15833== HEAP SUMMARY:
==15833== in use at exit: 0 bytes in 0 blocks
==15833== total heap usage: 79 allocs, 79 frees, 78,730 bytes allocated
==15833==
==15833== All heap blocks were freed -- no leaks are possible
==15833==
==15833== For counts of detected and suppressed errors, rerun with: -v
==15833== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)