Closed. This question is off-topic. It is not currently accepting answers. Learn more
想改进这个问题吗?Update the question所以堆栈溢出的值小于aa>。
三年前关闭。
我很难在我的pebble watch应用程序中找到一个奇怪的错误。我怀疑是记错了,但我找不到我的错误。我有一个字符串数组,当我调用menu_layer = menu_layer_create(bounds);时,它似乎在某种程度上损坏我的字符串。我在下面更详细地解释。错误的描述以粗体显示。
我有一个头文件,它将三个变量声明为外部变量,因此它们是全局的。
//externs.h
#ifndef EXTERNS_H
#define EXTERNS_H

// These global variables are accessible by all source files. Modified in main.c
extern int str_count;
extern char **str_titles;
extern char **str_teasers;

#endif

这三个变量在main.c中修改,但在其他c文件中使用。下面是我的main.c文件的一个示例,我在其中设置字符串数组str_titlesstr_teasers。结构info包含两个很长但用分隔符|分隔的字符串。我将这些字符串复制到一个临时缓冲区s_buffer中,并用strtok对它们进行解析,将每个新字符串保存到字符串数组中。
这似乎工作得很好,我检查了for循环中的每个字符串,最后一个字符总是以空结尾的字节,前面的一个是句点(句子的结尾)。我不在任何地方修改这些值,而且直到程序结束时才释放它们(因为它们应该存在于程序的生命中)。
我创建了一个具有动态条目数的菜单(在本例中是6个),每个菜单都有str_titles中6个字符串之一的标题。这里没有问题。我可以在程序中随时迭代并APP_LOG这个字符串数组。
当按下每个菜单项时,它应该在滚动层中显示str_teasers中的较长字符串。它只对前三个菜单项可靠地执行此操作。最后三个总是空的。尝试在这里用APP_LOG迭代和打印字符串数组,会在pebble日志使用的python框架中产生一系列错误,并且总是以如下内容结尾:
UnicodeDecodeError: 'utf8' codec can't decode byte 0x98 in position 0: invalid start byte

最后一部分有时是不同的,解码字节和位置根据字符串而改变。请注意,在日志中,对于最后三个空白菜单项总是会产生一些错误,只有在前三个菜单项出现错误的时候,即使滚动层不是空白的并且显示了正确的文本(对于前三个菜单项,有时它会毫无问题地打印到日志中)。
我在不同的地方尝试过invalid start byte打开APP_LOG,当它失败时,它会在我调用str_teasers创建菜单后这样做。在我打电话之前,我可以用APP_日志打印所有字符串,没有任何问题。我以为这是堆损坏错误,但在创建层之前和之后,我有可用的堆内存(约8100字节),我的应用程序不会崩溃。
也许我遗漏了一些很简单的东西,但我找不到我的错误。我相信我已经为menu_layer = menu_layer_create(bounds);正确地分配了内存,所以我根本不明白为什么要修改它。我在下面提供了一个修改后的示例代码以供参考。
//main.c
#include "strtok.h"
#include "externs.h"

int str_count;
char **str_titles;
char **str_teasers;

char *s_buffer;
const char delim[1] = "|";
char *token;

typedef struct {
  int s_count;
  char* s_titles;
  char* s_teasers;
} s_info;
s_info info;


// Sample code

str_count = info.s_count;

// Declare arrays of appropriate size
str_titles = malloc(str_count * sizeof(char*));
str_teasers = malloc(str_count * sizeof(char*));

// This creates a copy of the entire string s_titles into s_buffer
int len = strlen(info.s_titles) + 1;
s_buffer = (char *)malloc(len);
strcpy(s_buffer, info.s_titles);

token = strtok(s_buffer, delim); // Get the first token for the titles

// Walk through the other tokens
int counter = 0;
while(token != NULL) {
  *(str_titles + counter) = malloc((strlen(token) + 1) * sizeof(char));
  *(str_titles + counter) = token;
  token = strtok(NULL, delim);
  counter++;
}

// This creates a copy of the entire string s_teasers into s_buffer
len = strlen(info.s_teasers) + 1;
s_buffer = (char *)realloc(s_buffer, len);
strcpy(s_buffer, info.s_teasers);

token = strtok(s_buffer, delim); // Get the first token for the teasers

// Walk through the other tokens
counter = 0;
while(token != NULL) {
  *(str_teasers + counter) = malloc((strlen(token) + 1) * sizeof(char));
  *(str_teasers + counter) = token;
  token = strtok(NULL, delim);
  counter++;
}
free(s_buffer);

最佳答案

在这个代码块中

// Walk through the other tokens
int counter = 0;
while(token != NULL) {
  *(str_titles + counter) = malloc((strlen(token) + 1) * sizeof(char));
  *(str_titles + counter) = token;
  token = strtok(NULL, delim);
  counter++;
}

分配内存,但立即用标记指针覆盖指针。然后,在另一个类似的代码块中,重写了这些点所指向的字符串。自从内存被重新分配以来,您可能是“幸运的”,而之前的字符串内存仍然没有被其他进程所影响。实际上,您最终还是释放了这个字符串缓冲区,而没有复制标记。
我想你需要一个
// Walk through the other tokens
int counter = 0;
while(token != NULL) {
  *(str_titles + counter) = malloc((strlen(token) + 1) * sizeof(char));
  strcpy(*(str_titles + counter), token);         // <<--- here
  token = strtok(NULL, delim);
  counter++;
}

类似地,对于teasers代码块。
我还注意到,您通过strcpy索引,但没有对照提供给您的counter进行检查,后者用于为字符串指针数组分配内存。

关于c - 调用menu_layer时字符串损坏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36206418/

10-12 22:21
查看更多