我在尝试 运行 execve 时得到了错误的地址
I get bad address when trying to run execve
所以我正在尝试一个字符串向量,其中包含我想尝试的参数和 运行 使用 execve 命令。我也在复制环境,因为我正在编写的应用程序需要从进程中获取传入环境的副本。此应用程序是用 C++ 编写的,我从 execve 调用中收到 "Bad Address" 错误。这是我当前的代码:
#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 指针的方式不正确,或者我遗漏了一些非常明显的东西。谢谢
你的代码的问题是你的环境列表和
参数列表已 NULL
终止。然后你更新了你的代码
我的建议:
What has valgrind to do with that? You do my_array = new char*[random.size() + 1];
and after the loop making the copies, you do 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(就像在我的循环示例中一样)并且您已经分配了
space for 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)
所以我正在尝试一个字符串向量,其中包含我想尝试的参数和 运行 使用 execve 命令。我也在复制环境,因为我正在编写的应用程序需要从进程中获取传入环境的副本。此应用程序是用 C++ 编写的,我从 execve 调用中收到 "Bad Address" 错误。这是我当前的代码:
#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 指针的方式不正确,或者我遗漏了一些非常明显的东西。谢谢
你的代码的问题是你的环境列表和
参数列表已 NULL
终止。然后你更新了你的代码
我的建议:
What has valgrind to do with that? You do
my_array = new char*[random.size() + 1];
and after the loop making the copies, you domy_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(就像在我的循环示例中一样)并且您已经分配了
space for 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)