(前言我的C很可怕)
我尝试将字符串从iOS发送到BLE设备。我在swift中对字符串进行编码并将其写为:
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
的{{1}},如下所示:
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];
我有一个接受新userId的函数,然后从中创建一个新的Event并将其添加到链接列表中......这就是它想要做的事情:
/**
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;
}
目前,如果我运行上面的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
我得到了#34;崩溃"。我在一个相当模糊的IDE(赛普拉斯的PSoC Creator)中这样做,所以我没有看到任何错误日志或IDE崩溃日志。我能告诉的唯一方法是永远不会调用//enqueueEvent("2007-03-01T13:00:20", "UC", currentlyConnectedUserID);
,所以我知道它必须是那条线。
如果我这样做,我能够成功创建并加入新活动:
showMessageInUART
我唯一想到的可能是数组的大小错了?也许?或者也许有一些尾随enqueueEvent("2007-03-01T13:00:20", "UC", "1234567891234567891");
的事情搞砸了?
建议更新:
我试过这样做:
\0
它将正确的值赋予size_t destination_size = strlen(userId) + 1;
,但是入队仍会导致崩溃。
-
我已将currentlyConnectedUserID
替换为仍然导致崩溃的strcpy
;(
-
尝试这一点以确保我没有溢出仍然没有工作:
strncpy
更新
我将我的队列更新为这样,因为没有断点:
sprintf(currentlyConnectedUserID, "%.19s", userId);
这一行崩溃了:
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");
调用此功能,则可以正常工作。知道为什么当从不同的方法调用时它会崩溃吗?
答案 0 :(得分:1)
strcpy功能将源指向的C字符串复制到目标指向的数组中,包括终止空字符(并在此处停止)。
因此,我建议您使用enqueueEvent
而非危险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;
}
还将temp
指针从enqueueEvent
函数的本地堆栈的分配更改为全局级别,因为当超出函数时指针分配就消失了。