简体   繁体   English

结构中的字符串被覆盖,我不知道为什么

[英]A string inside a struct is being overwritten and I can't tell why

I've had this problem for the last two hours and I can't understand what's happening.过去两个小时我一直遇到这个问题,我不明白发生了什么。 I expect it to print this我希望它打印这个

ROBCO INDUSTRIES UNIFIED OPERATING SYSTEM
COPYRIGHT 2075-2077 ROBCO INDUSTRIES
-Server 6-

But instead it displays this但相反它显示这个

ROBCO INDUSTRIES UNIFIED OPERATING SYSTEM
COPYRIGHT Testing testing 123

I have no clue why this is happening but hopefully you will be able to help me.我不知道为什么会这样,但希望你能帮助我。 (If you want to know what this is for it's a Fallout Terminal Emulator). (如果你想知道这是一个辐射终端模拟器)。 Just ask if you nned any more details.只要问你是否有更多细节。 Thanks!谢谢!

It's being compiled like this if you need to know如果你需要知道,它是这样编译的

gcc test.c configParser.c -lconfig

test.c测试.c

#include <stdio.h>
#include "robco.h"

int main() {
  struct config_struct config;
  config = getConfig("test_config.cfg");

  printf("%s", config.banner);

  return 0;
}

configParser.c配置解析器

#include <stdio.h>
#include <libconfig.h>
#include <string.h>
#include "robco.h"

int cap(int num, int cap) {
  return (num > cap) ? cap : num;
}

struct config_struct getConfig(const char *filename)
{
  config_t cfg;
  config_setting_t *root, *menu, *options, *option;

  // Read the file. If there is an error, report it and exit.
  config_init(&cfg);
  config_read_file(&cfg, filename);

  root = config_root_setting(&cfg);

  // Get the banner from the config file if it exists, if not use the default set in robco.h
  const char *banner;

  if (! config_setting_lookup_string(root, "banner", &banner) ) {
    banner = DEFAULT_BANNER;
  }

  // Create the config struct and fill in the banner
  struct config_struct config;
  strcpy(config.banner, banner);

  // Get the menu
  menu = config_lookup(&cfg, "menu");

  // If it can't fetch the menu for any reason return -1
  if(! menu) {
    return;
  }

  // Get the options
  options = config_setting_get_member(menu, "options");

  if(! options) {
    return;
  }

  // Get number of options
  config.menu.num_options = cap(config_setting_length(options), MAX_OPTIONS);

  // Get the title. If it doesn't exist use the default
  const char *title;

  if (! config_setting_lookup_string(menu, "title", &title) ) {
    title = DEFAULT_TITLE;
  }

  strcpy(config.menu.title, title);

  // Loop through and get the text for all the options
  for(int i = 0; i < config.menu.num_options; ++i)
  {
    option = config_setting_get_elem(options, i);
    const char *text;

    config_setting_lookup_string(option, "text", &text);

    strcpy(config.menu.options[i].text, text);
  }

  return config;
}

robco.h robco.h

#define MAX_STRING_LENGTH 52
#define MAX_OPTIONS 5
#define DEFAULT_BANNER "ROBCO INDUSTRIES UNIFIED OPERATING SYSTEM\nCOPYRIGHT 2075-2077 ROBCO INDUSTRIES\n-Server 6-"
#define DEFAULT_TITLE "-=- TEST TITLE -=-"

struct option_struct {
  char text[MAX_STRING_LENGTH];
};

struct menu_struct {
  struct option_struct options[MAX_OPTIONS];
  int num_options;
  int selected;
  char title[MAX_STRING_LENGTH];
};

struct config_struct {
  char banner[MAX_STRING_LENGTH];
  struct menu_struct menu;
};

void printCenter(char msg[], int startRow);
void printMenuOption(char msg[], int startRow);
void drawMenu(struct menu_struct menu, int startRow);
void init_graphics();
struct config_struct getConfig(const char *filename);

test_config.cfg test_config.cfg

menu: {
   title: "Super Secret Valve Control Panel";
   options: (
    { 
      text: "Testing testing 123";
    },
    { 
      text: "THE SUN IS A DEADLY LASER";
    }
  );
};

Your default banner text is longer than MAX_STRING_LENGTH , so when you copy it to config.banner you write past the end of the array, leading to undefined behavior.您的默认横幅文本比MAX_STRING_LENGTH ,因此当您将其复制到config.banner您会写到数组的末尾,从而导致未定义的行为。

Make sure all your buffers are large enough to store the longest string you expect (accounting for the terminator), or truncate strings to the length of the buffer, or use dynamic memory and size the buffers as you need to.确保所有缓冲区都足够大以存储您期望的最长字符串(考虑到终止符),或者将字符串截断为缓冲区的长度,或者使用动态内存并根据需要调整缓冲区的大小。

I bet your MAX_STRING_LENGTH is too little and that you don't test for lengths.我敢打赌你的MAX_STRING_LENGTH太小了,而且你没有测试长度。 You must use strncpy and then don't forget to set the terminating null, which strncpy doesn't do.您必须使用strncpy然后不要忘记设置终止 null,而strncpy不会这样做。

You must also turn the warnings of your compiler on.您还必须打开编译器的警告。 I see struct config_struct getConfig but in that function you do some return s without a return value.我看到struct config_struct getConfig但在功能你做一些return没有返回值s。 The compiler should warn about that.编译器应该对此发出警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM