作者Keitaro (动き出す时间...)
看板C_and_CPP
标题[问题] 请问char**array的问题
时间Tue Nov 10 19:53:34 2020
开发平台(Platform): (Ex: Win10, Linux, ...)
Ubuntu 18.04 LTS
编译器(Ex: GCC, clang, VC++...)+目标环境(跟开发平台不同的话需列出)
gcc
程式码(Code):(请善用置底文网页, 记得排版,禁止使用图档)
https://ideone.com/jugcYC
重新上传完整原始码
补充说明(Supplement):
程式码如以上连结
想请教版上各位先进 我的程式码这一段是否出了什麽问题
这段code作用是这样的
1. 我要写一个自己用的CreateProcess() 在linux底下去call process起来做事
2. 中间是fork...exec 因为前面印出来就发现有问题了
我觉得应该是跟fork以後开始没关系
3. 传进来的参数
p_sAppName: process name
p_sCmdArg: parameter, 以空白切割, 所以我会去呼叫一个自己写的ParserCmd()
去把传进来的参数去parser成一个vector<string> 把所有参数放里面
ParserCmd()的结果我确定是对的所以忽略不贴
p_sEnvArg: 环境变数的参数, 作法如同上面的p_sCmdArg
p_nRetVal: 在fork()...exec()这段拿来回传呼叫process的成功或失败
假设我今天call这个function的呼叫方式是这样
MyCreateProcess("ffmpeg", "-vsync 0 -i file.cfg Compare.yuv");
p_sEnvArg/p_nRetVal有预设值NULL
我预计进入function後
1. 传进来的p_sCmdArg, 会被ParserCmd()拆解然後存每一个cmd在vector里面
2. 由於execve需要传参数/环境变数型态为char**, 所以我先
char **ppCmdArg = new char*[vCmdSet.size() + 1];
然後在回圈中, 针对於每一个ppCmdArg[i], 我再
ppCmdArg[i] = new char[vCmdSet[i].length() + 1];
由於参数不可能每个长度都相同 因此new出来的结果长度都不相同
3. 接下来我再把vector里面储存的参数字串拷贝到new出来的char* ppCmdArg[i]
4. 如果有传环境变数我也是做一样的处理 这次范例没有可以无视
5. 接着就把ppCmdArg给execve当参数呼叫process
结果我发现程式在结束的地方 我做delete[] array出了问题
然後我把这段程式码加了printf做debug
看到了无法理解的结果
输出:
-------------new--------------
ppCmdArg[0] = ffmpeg
ppCmdArg[1] = -vsync
ppCmdArg[2] = 0
ppCmdArg[3] = -i
ppCmdArg[4] = file.cfg
ppCmdArg[5] = Compare.yuv
-------------new end--------------
-------------test 1--------------
ppCmdArg[0] = ffmpeg
ppCmdArg[1] = (null)
ppCmdArg[2] = (null)
ppCmdArg[3] = -i
ppCmdArg[4] = file.cfg
ppCmdArg[5] = Compare.yuv
------------test 1 end--------------
------------test 2--------------
ppCmdArg[0] = ffmpeg
ppCmdArg[1] = (null)
ppCmdArg[2] = (null)
ppCmdArg[3] = -i
ppCmdArg[4] = file.cfg
ppCmdArg[5] = Compare.yuv
-------------test 2 end--------------
vCmdSet size = 6
ppCmdArg[0] = ffmpeg
ppCmdArg[1] = (null)
ppCmdArg[2] = (null)
ppCmdArg[3] = -i
free(): invalid pointer
Aborted (core dumped)
我new完, copy字串进去 可以正确printf
然後马上在test 1区块全部重印一次
结果ppCmdArg[1], ppCmdArg[2]变成NULL?
请教一下各位先进 是否我犯了什麽错?或者gcc编译的参数错了吗?
我用的是 -O2 -W -fPIC
先感谢各位了
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 210.242.38.175 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1605009218.A.846.html
1F:→ nh60211as: ppCmdArg[vCmdSet[i].length()] = 0; 你这行是做什麽的 11/10 20:32
2F:→ nh60211as: 还有你都写C++了有什麽必要是要用C-style字串吗 11/10 20:34
我把字串结尾设定为\0
您的意思是要怎麽用C++改写比较好呢?
3F:→ Lipraxde: L44、L62 在干嘛?省略 code 可以,但是请弄一个 minim 11/10 20:42
L42就是我说的每一个char* ppCmdArg[i]去new char array
L62一样是把字串结尾设定为\0
4F:→ Lipraxde: al working example 出来。不然看 code 还要脑补省略的 11/10 20:42
5F:→ Lipraxde: 部分有没有可能出问题很累,又不是在猜灯谜 = = 11/10 20:42
已经把完整code重新上传
请多多指教 感恩
※ 编辑: Keitaro (210.242.38.175 台湾), 11/10/2020 21:22:06
※ 编辑: Keitaro (210.242.38.175 台湾), 11/10/2020 21:22:29
6F:→ nh60211as: 字串的结尾是ppCmdArg[i][vCmdSet[i].length()] 11/10 21:28
7F:推 ucrxzero: 58行 ppCmdArg[vCmdSet[i].length()] = 0; 11/10 21:28
8F:→ ucrxzero: 错两个地方 11/10 21:28
9F:→ stucode: 其实一楼已经说出问题所在了,L58 11/10 21:29
10F:→ nh60211as: ppCmdArg[x]是char** ppCmdArg的第x个位置 11/10 21:29
11F:→ ucrxzero: ppCmdArg[i][vCmdSet[i].length()] = \0; 11/10 21:29
12F:→ ucrxzero: 不是0 是null才对 11/10 21:29
13F:→ ucrxzero: 刚好其他人都有解出来请楼主帮我把整个有我的推文全删 11/10 21:30
好喔
14F:推 ucrxzero: 还有strcpy本来就会复制\0过去了 11/10 21:32
15F:→ ucrxzero: 要不然strcpy这麽聪明就不会跟get一样列为危险函示了 11/10 21:32
16F:→ Lipraxde: 仔细对照一下 L56、L58、L61,再想想看 L58 真的有写出 11/10 22:01
17F:→ Lipraxde: 你想要的意思吗? 11/10 22:01
18F:→ Lipraxde: 当 i = 2 or 3 的时候 L58 做了什麽? 11/10 22:02
恍然大悟 唉我真的是蠢...
怎麽会这样写 看到楼上几位的点名真的是觉得自己蠢到家了犯这种错误...
可见自己二维阵列的观念生疏了QQ
非常感谢各位的指教
※ 编辑: Keitaro (210.242.38.175 台湾), 11/10/2020 22:13:53
19F:→ Lipraxde: 另外 L110~L129 建议是拿 man waitpid 里的范例来改 11/10 22:12
了解
20F:→ nh60211as: 抱歉,看到後面的code应该真的只能用char**来写 11/10 22:21
是的 我真的想不出其他写法
他参数型态要求char**然後我要写传任意参数的
想来想去也只能这样写
※ 编辑: Keitaro (210.242.38.175 台湾), 11/10/2020 22:31:14
21F:推 ucrxzero: C++写法 (可过): vector<char*> char_vtr 11/10 23:40
22F:→ ucrxzero: vector<char*> env_vtr 11/10 23:41
23F:→ ucrxzero: execve(proc_name, &char_vtr, &env_vtr) 11/10 23:41
24F:→ ucrxzero: execve(proc_name, &char_vtr[0], &env_vtr[0]) 11/10 23:42
25F:→ ucrxzero: 但不建议使用 11/10 23:43
26F:→ Killercat: 好像并不是所有的STL都保证data记忆体位置在前面 11/27 14:25
27F:→ Killercat: 建议用std::vector::data取得资料段的pointer比较保险 11/27 14:25