作者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://www.ptt.cc/bbs/C_and_CPP/M.1605009218.A.846.html
→ nh60211as: ppCmdArg[vCmdSet[i].length()] = 0; 你這行是做什麼的 11/10 20:32
→ nh60211as: 還有你都寫C++了有什麼必要是要用C-style字串嗎 11/10 20:34
我把字串結尾設定為\0
您的意思是要怎麼用C++改寫比較好呢?
→ Lipraxde: L44、L62 在幹嘛?省略 code 可以,但是請弄一個 minim 11/10 20:42
L42就是我說的每一個char* ppCmdArg[i]去new char array
L62一樣是把字串結尾設定為\0
→ Lipraxde: al working example 出來。不然看 code 還要腦補省略的 11/10 20:42
→ 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
→ nh60211as: 字串的結尾是ppCmdArg[i][vCmdSet[i].length()] 11/10 21:28
推 ucrxzero: 58行 ppCmdArg[vCmdSet[i].length()] = 0; 11/10 21:28
→ ucrxzero: 錯兩個地方 11/10 21:28
→ stucode: 其實一樓已經說出問題所在了,L58 11/10 21:29
→ nh60211as: ppCmdArg[x]是char** ppCmdArg的第x個位置 11/10 21:29
→ ucrxzero: ppCmdArg[i][vCmdSet[i].length()] = \0; 11/10 21:29
→ ucrxzero: 不是0 是null才對 11/10 21:29
→ ucrxzero: 剛好其他人都有解出來請樓主幫我把整個有我的推文全刪 11/10 21:30
好喔
推 ucrxzero: 還有strcpy本來就會複製\0過去了 11/10 21:32
→ ucrxzero: 要不然strcpy這麼聰明就不會跟get一樣列為危險函示了 11/10 21:32
→ Lipraxde: 仔細對照一下 L56、L58、L61,再想想看 L58 真的有寫出 11/10 22:01
→ Lipraxde: 你想要的意思嗎? 11/10 22:01
→ Lipraxde: 當 i = 2 or 3 的時候 L58 做了什麼? 11/10 22:02
恍然大悟 唉我真的是蠢...
怎麼會這樣寫 看到樓上幾位的點名真的是覺得自己蠢到家了犯這種錯誤...
可見自己二維陣列的觀念生疏了QQ
非常感謝各位的指教
※ 編輯: Keitaro (210.242.38.175 臺灣), 11/10/2020 22:13:53
→ Lipraxde: 另外 L110~L129 建議是拿 man waitpid 裡的範例來改 11/10 22:12
瞭解
→ nh60211as: 抱歉,看到後面的code應該真的只能用char**來寫 11/10 22:21
是的 我真的想不出其他寫法
他參數型態要求char**然後我要寫傳任意參數的
想來想去也只能這樣寫
※ 編輯: Keitaro (210.242.38.175 臺灣), 11/10/2020 22:31:14
推 ucrxzero: C++寫法 (可過): vector<char*> char_vtr 11/10 23:40
→ ucrxzero: vector<char*> env_vtr 11/10 23:41
→ ucrxzero: execve(proc_name, &char_vtr, &env_vtr) 11/10 23:41
→ ucrxzero: execve(proc_name, &char_vtr[0], &env_vtr[0]) 11/10 23:42
→ ucrxzero: 但不建議使用 11/10 23:43
→ Killercat: 好像並不是所有的STL都保證data記憶體位置在前面 11/27 14:25
→ Killercat: 建議用std::vector::data取得資料段的pointer比較保險 11/27 14:25