Foa*_*oad -6 c++ segmentation-fault argv command-line-arguments
为了解决我的问题在这里,我想知道是否/如何我可以比在格式定义的命令行参数的第二个变量其他char** argv或char* argv[]。原因是 pybind11 不允许函数输入中的任何一个。以下是我尝试过的方法:
#include <stdio.h>
int main(int argc, int* argv_){
for (int i = 0; i < argc; ++i){
printf("%s\n", (char *)(argv_[i]));
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法背后的基本原理是指针本质上是一个整数,通过将地址转换为char指针,人们应该能够获得字符串。提前感谢您的支持。
#include <stdio.h>
#include <string>
int main(int argc, std::string* argv_){
for (int i = 0; i < argc; ++i){
printf("%s\n", argv_[i].c_str());
}
}
Run Code Online (Sandbox Code Playgroud)
#include <stdio.h>
#include <string>
#include <vector>
int main(int argc, std::vector<std::string> argv_){
for (int i = 0; i < argc; ++i){
const char* argv__ = argv_[i].c_str();
printf("%s\n", argv_[i].c_str());
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,上述所有方法都会导致臭名昭著的segmentation fault.
如果您能帮助我了解问题所在(即内存泄漏在哪里)以及如何解决这些问题,我将不胜感激。
在评论中我被告知,如果使用任何其他形式而不是main(), main(int argc, char** argv), 或main(int argc, char* argv[]),它将不可避免地导致segmentation fault. 但是,下面的代码有效:
#include <stdio.h>
int main(int argc, long* argv_){
for (int i = 0; i < argc; ++i){
printf("%s\n", (char *)(argv_[i]));
}
}
Run Code Online (Sandbox Code Playgroud)
这适用于 Ubuntu 最小g++ 7.4.0和 Windows 10 Visual Studio 2019 编译器。但是,它不与clang. 正如其他人指出的那样,这不是解决方案,而且是一种非常糟糕的做法。根据编译器、操作系统和内存的当前状态,它可能会导致未定义的行为。这不应该在任何实际代码中使用。在任何C / C ++代码的主要功能必须的形式main(),main(int argc, char** argv)或main(int argc, char* argv[])。
main毕竟它看起来并不需要,所以你可以这样做:
#include <iostream>
#include <string>
#include <vector>
int cppmain(std::string program, std::vector<std::string> args) {
std::cout << program << " got arguments:\n";
for(auto& arg : args) {
std::cout << " " << arg << "\n";
}
return 0;
}
int main(int argc, char* argv[]) {
// create a string from the program name and a vector of strings from the arguments
return cppmain(argv[0], {argv + 1, argv + argc});
}
Run Code Online (Sandbox Code Playgroud)
如果您需要调用类似于 main 的闭源函数(您无法更改),请创建一个可以pybind调用的包装函数,并让该函数调用闭源函数。
#include <cstddef>
#include <iostream>
#include <string>
#include <vector>
int closed_source_function(int argc, char* argv[]) {
for(int i = 0; i < argc; ++i) {
std::cout << argv[i] << '\n';
}
return 0;
}
int pybind_to_this(std::vector<std::string> args) {
// create a char*[]
std::vector<char*> argv(args.size() + 1);
// make the pointers point to the C strings in the std::strings in the
// std::vector
for(size_t i = 0; i < args.size(); ++i) {
argv[i] = args[i].data();
}
// add a terminating nullptr (main wants that, so perhaps the closed source
// function wants it too)
argv[args.size()] = nullptr;
// call the closed source function
return closed_source_function(static_cast<int>(args.size()), argv.data());
}
Run Code Online (Sandbox Code Playgroud)
让我们试着一一解决在冗长的讨论中出现的大量问题。
问题 1:为什么在使用某些非标准参数(如字符串向量或 int 指针)时会出现段错误main?
int, char **C 和 C++ 标准都以这种方式定义了的参数类型。除了非标准扩展之外,您不能使用其他类型。
来自 ISO/IEC 9899(C 语言),5.1.2.2.1 程序启动:
程序启动时调用的函数名为 main。实现声明没有此函数的原型。它应定义为返回类型
int并且不带参数:
int main(void) { /* ... */ }或带有两个参数(这里称为
argcandargv,尽管可以使用任何名称,因为它们对于声明它们的函数是本地的):
int main(int argc, char *argv[]) { /* ... */ }或同等学历; 或以其他一些实现定义的方式。
最后一句话允许我提到的那些扩展。我知道的一个这样的扩展是 GCC 的environ:
https://www.gnu.org/software/libc/manual/html_node/Program-Arguments.html#Program-Arguments
问题 2:我如何解决这个问题?
你没有。
使用与标准或编译器扩展定义的类型不同的类型是Undefined Behavior,它可以 - 但不需要 - 导致段错误。不要调用未定义的行为。不要“绕过”标准。它不是“解决方法”,更不是“解决方案”,它是随时可能在您面前炸毁的损坏代码。
问题 3:如何使用pybindachar **作为参数的第三方函数?
你不这样做,因为这不是一个由支持的数据类型pybind。
问题 4:那么,我如何通过 接口来实现这样的功能pybind呢?
您编写了一个包装函数,在前端,该函数采用(eg )支持的参数,适当地编组这些参数,然后使用编组后的参数为您调用第三方后端函数。(然后,当然,如果需要,对返回类型反向执行相同的操作。)pybindstd::vector< std::string >
有关如何执行此操作的惯用示例,请参阅@TedLyngmo 的答案。
问题5:我pybind可以给第三方main吗?
这是不明智的,因为这main是一个特殊的函数,被调用的代码可能会做出假设(如atexit回调),你的调用代码不遵守,也不能遵守。它当然不是第三方所期望的作为库函数调用的函数。
| 归档时间: |
|
| 查看次数: |
666 次 |
| 最近记录: |