簡體   English   中英

為什么此代碼將歌曲名稱列表隨機化會產生分段錯誤?

[英]Why does this code to randomize a list of song names generate a segmentation fault?

我正在嘗試創建一個程序,該程序從用戶那里接收12個歌曲標題,然后以隨機順序形成一個列表。 我使用了gets()函數和內存分配,以便將輸入放置到這樣的數組中:

 argv[0] = song1, argv[1] = song2, argv[2] = song3 (etc.). 

輸入實際的歌曲,然后通過randomize和createSetList()函數運行它時,似乎存在常見的分段錯誤錯誤。 但是,如果要廢棄內存分配和硬代碼,它將可以正常工作。 我的意思是這樣的:

char *input[ SONG ] =
  { "song1", "song2", "song3", "song4",
      "song5", "song6", "song7", "song8",
        "song9", "song10", "song11", "song12", "song13" };

雖然,我的目的是讓用戶在運行時輸入歌曲名稱。 分段錯誤錯誤的原因是什么?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define SONG 13
#define SETSIZE 5
// prototypes

void randomize( unsigned int wDeck[ SONG ] ); 
void createSetList( unsigned int wDeck[ SONG ], char *wFace[] ); 

int main( void ){

printf("Please enter the songs you want to play!\n");
printf("I will create the set list and randomize it for you!\n");


char input[100];
char *argv[ SONG ];
char *token;

 /*memory allocation for inputting song titles into a single array*/
 /*****memory allocation code starts here********/
 gets(input);
   token = strtok(input, " ");
     int i=0;
       while( token != NULL ) {
         argv[i] = malloc(strlen(token) + 1);
           strncpy(argv[i], token, strlen(token));
             i++;
      token = strtok(NULL, " ");
    } 
       argv[i] = NULL; //argv ends with NULL
         /***memory allocation code ends here*****/

         unsigned int setList[ SONG ] = { 0 };
           srand( time( NULL ) ); // seed random-number generator
             randomize( setList ); // shuffle the list
                createSetList( setList, argv ); // create the setlist
 } //end of main





/*SHUFFLE FUNCTION*/
   void randomize( unsigned int wDeck[ SONG ] ){

     size_t column;
      size_t c;

 for ( c = 1; c <= SETSIZE; ++c ) {
     do {
       column = rand() % SONG;
         } while( wDeck[ column ] != 0 );

               wDeck[ column ] = c;}}

    /* Create Set List Function */
 void createSetList( unsigned int wDeck[ SONG ],  char *wFace[] ){

    size_t c;
     size_t column;

      for ( c = 1; c <= SETSIZE; ++c ) {

        for ( column = 0; column < SONG; ++column ) {

          if ( wDeck[ column ] == c ) {

             printf( "%s\n", wFace[ column ]); 
                }}}}

在您的代碼中

strncpy(argv[i], token, strlen(token));

用法是錯誤的。 您還需要復制終止的空字節。

strncpy()手冊頁中可以看到

除了最多復制nsrc字節外, strncpy()函數strncpy()類似。

警告:如果src的前n個字節中沒有空字節,則放置在dest的字符串將不會以空終止。

如我的@chqrlie先生的評論中所述,並在@Keith Thompson精彩文章中進行解釋 ,您不應使用strncpy() 為了安全起見,可以使用strdup()避免malloc() + strcpy()的開銷( 和陷阱 strcpy()

偽碼

 argv[i] = strdup(token);

將以有效的方式完成這項工作。 請記住,您仍然需要通過strdup()free()返回的指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM