2016-09-27 79 views
1

(以前言本我的C是可怕的)试图复制字符数组结构崩溃

我试图从iOS版发送一个字符串到BLE装置。我在编码的迅速串并把它写这样的:

func sendUserName(userName: String) { 
    let bytes: [UInt8] = Array(userName.utf8) 

    print(bytes.count) 

    let data = NSData(bytes: bytes, length: bytes.count) 
    capsenseLedBoard!.writeValue(data, forCharacteristic: userIdCharacteristic, type: CBCharacteristicWriteType.WithResponse) 
} 

我在此字符串"THISISATEST123456789"这行print(bytes.count)打印出来20发送。


我收到这样的BLE装置上的数据,并将其传递到下面userDidConnect功能:

userDidConnect((char *)wrReqParam->handleValPair.value.val); 

我有一个struct称为Event,看起来像这样:

struct Event { 
    char time[20]; // The time in ISO 1601 format 
    char name[3]; // The two character name of the event. See header for declarations. 
    char userId[20]; // The userId of the connected user if one is present. 
    struct Event* next; 
}; 

我有一个全局变量声明如下:

char currentlyConnectedUserID[20]; 

然后我有一个排队的功能,看起来像这样:

/** 
Creates a new Event and adds to the linked list. 

@param time The time in ISO 8601 format. 
@param name The name descriptor of the event ("VS", "VO", etc.) 
@param userId The id of the user who is currently connect (if they are connected). 
*/ 
    void enqueueEvent(char time[20], char name[3], char userId[20]) { 

    struct Event* temp = (struct Event*)malloc(sizeof(struct Event)); 
    strncpy(temp->time, time, 20); 
    strncpy(temp->name, name, 3); 
    strncpy(temp->userId, userId, 20); 
    temp->next = NULL; 

    if(front == NULL && rear == NULL) { 
     front = rear = temp; 
     return; 
    } 
    rear->next = temp; 
    rear = temp; 
} 

我有接受新功能userId,然后创建一个新的事件,并将其添加到链接列表..这是它是假设要做的:

void userDidConnect(char *userId) 
{ 
    size_t destination_size = sizeof(userId); 
    snprintf(currentlyConnectedUserID, destination_size, "%s", userId); 
    //enqueueEvent("2007-03-01T13:00:20", "UC", currentlyConnectedUserID); 

    showMessageInUART(currentlyConnectedUserID, sizeof(currentlyConnectedUserID)); 
} 

目前,如果我运行userDidConnect上述方法我能够正确地打印出currentlyConnectedUserID。但是,如果我取消注释此行:

//enqueueEvent("2007-03-01T13:00:20", "UC", currentlyConnectedUserID); 

我得到一个“崩溃”。我在一个相当模糊的IDE(赛普拉斯的PSoC Creator)中这样做,所以我没有看到任何错误日志或IDE崩溃日志。我唯一能说的是,showMessageInUART从未被调用过,所以我知道它必须是这条线。

我能够成功地创建和排队一个新的事件,如果我这样做:

enqueueEvent("2007-03-01T13:00:20", "UC", "1234567891234567891"); 

我唯一的想法是,也许该数组的大小是错误的?也许?或者也许有一些尾随\0这是搞砸了?


建议更新:

我试着这样做:

size_t destination_size = strlen(userId) + 1; 

这给正确的值到然而currentlyConnectedUserID入队仍然会导致系统崩溃。

-

我已经更换了strcpystrncpy这仍然是导致飞机坠毁;(

-

试过这个,以确保我没有溢出仍然没有工作:

sprintf(currentlyConnectedUserID, "%.19s", userId); 

UPDATE

我更新了我的排队看起来是这样,因为没有断点:

void enqueueEvent(char time[20], char name[3], char userId[20]) { 

    UART_UartPutString("start enqueue"); 

    struct Event* temp = (struct Event*)malloc(sizeof(struct Event)); 

    UART_UartPutString("1"); 

    strncpy(temp->time, time, 20); 

    UART_UartPutString("2"); 

    strncpy(temp->name, name, 3); 

    UART_UartPutString("3"); 

    strncpy(temp->userId, userId, 20); 

    UART_UartPutString("4"); 

    temp->next = NULL; 

    UART_UartPutString("5"); 

    if(front == NULL && rear == NULL) { 
     front = rear = temp; 
     return; 
    } 
    rear->next = temp; 
    rear = temp; 
} 

此行崩溃:

strncpy(temp->time, time, 20);

又名我们从来没有让在这里: UART_UartPutString("2");

如果我从main调用这个相同的函数,它会很好。任何想法为什么它会在这里崩溃时从不同的方法调用?

+0

我怀疑'userDidConnect'没有做你想做的。 'userId'是一个指针,所以'sizeof(userId)'将在32位机器上返回4,在64位机器上返回8。如果'userId'指向一个字符串,我敢打赌你想要字符串长度。 – yano

+0

@yano我试着用'strlen'替换'sizeof',它仍然给我正确的转换到'currentlyConnectedUserID'然而排队仍然崩溃:( – random

+0

然后'sizeof(userId)+ 1'将返回5或9取决于你的我的猜测是你有字符串的问题,但是这里没有足够的代码来确认,你传递给'userDidConnect'的什么东西? – yano

回答

1

strcpy函数将源指向的C字符串复制到目标指向的数组(包括终止空字符(并在该点停止))。 因此,我建议你改变enqueueEvent funtion,用strncpy而不是危险strcpy为:

void enqueueEvent(char time[20], char name[3], char userId[20]) { 

    struct Event* temp = (struct Event*)malloc(sizeof(struct Event)); 
    strncpy(temp->time, time,20); 
    strncpy(temp->name, name,3); 
    strncpy(temp->userId, userId,20); 
    temp->next = NULL; 

    if(front == NULL && rear == NULL) { 
     front = rear = temp; 
     return; 
    } 
    rear->next = temp; 
    rear = temp; 
} 

变化也从enqueueEvent功能,全球范围内的局部栈temp指针的分配,因为指针分配消失当走出功能。

+0

我是否应该对我的问题的第一条评论做推荐更改? – random

+2

请注意'strncpy'。它不保证复制一个终止的''\ 0',因此当它在拷贝过程中不会溢出缓冲区时,如果它们没有空终止符,那么你可以在访问/修改这些字符串的路上遇到麻烦。 – yano

+1

另一个指向调查是'currentlyConnectedUserID'值:你怎么确定它的长度小于20个字符(包括\ 0)? –