は、コードを困難に見て、コンパイルし、それを試した、私は「当面の問題はあなたのことであるとのanalysis」M.Mに同意します再 ヌルポインタにコピーしようとしています。
しかし、あなたは一般的にメモリ管理を慎重に検討していないと思われます。 strcpy(tempStr, one);
を実行すると、ソース文字列が割り当てられたメモリにコピーされます。 (Un)幸いにも、あなたは必要なコピーよりもはるかに多くのメモリを割り当てました。続いてstrcpy(tempStr, fronttoken);
を実行するときは、元のコピーone
の後にfronttoken
をtempStr
にコピーします。その後、それを分割します。
tempStr
がヌルに設定されていて、ヌルポインタにコピーすると、strcpy(tempStr, backtoken)
が試行されたため、クラッシュする可能性があります。
これを修正すると、重複する文字列のコピーの問題に遭遇する可能性があります。現在のバックトークンのセットは十分に小さいので問題はありませんが、100バイトのバックトークンがあれば、重複するストリングコピーと未定義の動作が発生します。
このコードは、問題を示して修正します。トークンの周囲に角括弧が含まれているため、見つかったものを正確に見るのが簡単です。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char* one = "hello, my, name, is, code monkey, \"This, is a title\", more, random, stuff\n";
char* tempStr= malloc(1000);
void* freeTempStr = tempStr;
strcpy(tempStr, one);
printf("tempStr = [%p .. %p)\n", (void *)tempStr, (void *)(tempStr + 1000));
char* fronttoken = strsep(&tempStr, "\"");
printf("tempStr = %p; fronttoken = %p\n", (void *)tempStr, (void *)fronttoken);
char* title = strsep(&tempStr, "\"");
printf("tempStr = %p; title = %p\n", (void *)tempStr, (void *)title);
char* backtoken = strsep(&tempStr, "\n");
printf("tempStr = %p; backtoken = %p\n", (void *)tempStr, (void *)backtoken);
char* token;
printf("tempStr = %p; fronttoken = %p - before strcpy 1\n", (void *)tempStr, (void *)fronttoken);
strcpy(tempStr, fronttoken);
token = strsep(&tempStr, ",");
while (token != NULL)
{
printf("Front tokens: %p [%s]\n", (void *)token, token);
token = strsep(&tempStr, ",");
}
printf("Title: [%s]\n", title);
printf("tempStr = %p; backtoken = %p - before strcpy 2 (unfixed)\n", tempStr, backtoken);
tempStr = freeTempStr;
printf("tempStr = %p; backtoken = %p - before strcpy 2 (fixed - but beware overlap)\n", tempStr, backtoken);
strcpy(tempStr, backtoken);
token = strsep(&tempStr, ",");
while (token != NULL)
{
printf("Back tokens: %p [%s]\n", (void *)token, token);
token = strsep(&tempStr, ",");
}
free(freeTempStr);
return 0;
}
出力例(Macがインストールされているセキュリティ更新2017から001に、MacOSのハイシエラ10.13.1を実行している - macOS 10.13.1 (17B1002)
- あなたはまだ行っていないしている場合はそれをインストール!):
tempStr = [0x7fb91ac02880 .. 0x7fb91ac02c68)
tempStr = 0x7fb91ac028a3; fronttoken = 0x7fb91ac02880
tempStr = 0x7fb91ac028b4; title = 0x7fb91ac028a3
tempStr = 0x7fb91ac028ca; backtoken = 0x7fb91ac028b4
tempStr = 0x7fb91ac028ca; fronttoken = 0x7fb91ac02880 - before strcpy 1
Front tokens: 0x7fb91ac028ca [hello]
Front tokens: 0x7fb91ac028d0 [ my]
Front tokens: 0x7fb91ac028d4 [ name]
Front tokens: 0x7fb91ac028da [ is]
Front tokens: 0x7fb91ac028de [ code monkey]
Front tokens: 0x7fb91ac028eb [ ]
Title: [This, is a title]
tempStr = 0x0; backtoken = 0x7fb91ac028b4 - before strcpy 2 (unfixed)
tempStr = 0x7fb91ac02880; backtoken = 0x7fb91ac028b4 - before strcpy 2 (fixed - but beware overlap)
Back tokens: 0x7fb91ac02880 []
Back tokens: 0x7fb91ac02881 [ more]
Back tokens: 0x7fb91ac02887 [ random]
Back tokens: 0x7fb91ac0288f [ stuff]
デバッガを使用すると、この問題をかなり早く見つけることができます。
あなたは何をしようとしているのか分かりません。本当に 'strsep()'の動作を理解していますか? – Stargateur
セパレータが見つからない場合、 'strsep'は' tempStr'を 'NULL'に設定します。したがって、おそらく' strcpy'の最初の引数としてNULLを渡してsegfaultを引き起こします。この仮説をテストするには、デバッガを使用し、segfaultが起きたときに 'tempStr'の値を調べてください。 –
@Stargateurムービー属性を含む大きなCSVファイルを正しくトークン化しようとしています。映画の中にはタイトルのカンマがあるものがあります。そのため、タイトルのカンマを囲むために前後のトークンがあります。 – codemonkey