使用gcc而不是使用clang在for循环错误中分配结构

时间:2017-02-19 00:15:32

标签: c gcc clang c11 gcc5

您好我在使用以下命令编译的C11程序上使用gcc(版本5.4.0)收到此警告:

$ gcc -g -Wall -std=c11 main.c -o minishell   
main.c: In function ‘process_new’:
main.c:184:10: error: assignment of read-only variable ‘s’
        s = slice_next(s, ':')) {

clang(版本3.8.0)没有任何内容:

$ clang -g -Wall -std=c11 main.c -o minishell # Compile without warning.

我在Ubuntu 16.04上。

这是代码

// The loop that generate the warning with gcc.
for (str_slice s = slice_at(paths, ':');
       !slice_empty(s);
       s = slice_next(s, ':')) {
//       ^ Gcc complains here.
    const char *full_path = build_full_path(progname, s);
    /* I use with full_path but nothing with s after this point. */ 
    // There is no aliasing on full_path at this point.
    free((void *)full_path); .
  }

这里是str_slice

的定义
typedef struct _str_slice {
  const char* data;
  const uint32_t len; // end - data len of slice.
//^^^^^ Source of gcc warning.
} str_slice;

使用它的功能:

inline
uint32_t slice_len(const str_slice slice) {
  return slice.len;
}

inline
const char* slice_data(const str_slice s) {
  return s.data;
}

inline
str_slice slice_new(const char* data, uint32_t len) {
  return (str_slice) { data, len };
}

inline
str_slice slice_at(const char* data, const char c) {
  const char* end = strchr(data, c);
  return slice_new(data, end - data);
}

inline
str_slice slice_next(const str_slice s, const char c) {
  const char* data = slice_data(s) + slice_len(s) + 1; // skip c
  const char* end = strchr(data, c);
  if (end != NULL) {
    return slice_new(data, end - data);
  } else {
    return slice_new(NULL, 0);
  }
}

inline
bool slice_empty(const str_slice s) {
  return s.len == 0;
}

如有必要,请提供有关build_full_path

的代码
const char* build_full_path(const char* progname, const str_slice slice) {
  size_t len_progname = strlen(progname);
  // Save additional 2 bytes for adding '/' and '\0'.
  size_t full_path_size = len_progname + slice.len + 2; 
  size_t malloc_size = sizeof(char) * full_path_size;
  char *full_path = malloc(malloc_size);

  full_path[full_path_size - 1] = '\0';
  memcpy(full_path, slice.data, slice.len);
  full_path[slice.len] = '/';
  memcpy(full_path + slice.len + 1, progname, len_progname);

  return (const char *) full_path;
}

使用clang编译时,我得到了一个具有良好行为的可执行文件。 所以我做错了什么?或者我发现了一个错误?

这是我的程序的完整代码(过时):https://gist.github.com/darnuria/12af88c509310c2b40e0031522882720

修改:使用memcpy代替strncpy。删除标量类型的const。

1 个答案:

答案 0 :(得分:1)

在结构中,数据成员len被声明为常量数据成员。

typedef struct _str_slice {
  const char* data;
  const uint32_t len; // end - data len of slice.
  ^^^^^^     
} str_slice;

这意味着它可以被更改,因此您可能无法将结构的一个对象分配给结构的另一个对象。