簡體   English   中英

為什么我的結構在包含字符串時崩潰?

[英]why my struct crash when it contains string?

我遇到了一個問題,我認為了解 std::string 非常有意義。

我用c設計了一個隊列(無鎖隊列),代碼是:kfifo.c

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define min(X,Y) ((X) < (Y) ? (X) : (Y))

struct kfifo{
    char* buffer;  // data address pointer
    unsigned int index[96];
};

static unsigned long roundup_pow_of_2(unsigned long n) {  // calculate the nearest pow(2) value of n
// so the % operation can be replaced by bit operation &, which is faster
  unsigned long rval = 1;
  while (rval < n) rval <<= 1;
  return rval;
}

static bool is_power_of_2(unsigned long n) {
  return (n != 0 && ((n & (n - 1)) == 0));
}

static void kfifo_init(struct kfifo* fifo,  char* buffer, unsigned int size, size_t elemSize) {
  // init struct
  assert(is_power_of_2(size));
  memset(fifo->index, 0, sizeof(fifo->index));
  fifo->buffer = buffer;
  fifo->index[51] = elemSize;
  fifo->index[34] = size < 2 ? 0: size;
}

int kfifo_alloc(struct kfifo* fifo, unsigned int size, size_t elemSize) {
  /* 
  * round up to the next power of 2, since our 'let the indices 
  * wrap' tachnique works only in this case. 
  */
  if (!is_power_of_2(size)) {
    size = roundup_pow_of_2(size);
  }

  // allocate memory
  char* buffer = (char*)malloc(size * elemSize);
  if (!buffer)
    return 0;

  // init struct
  kfifo_init(fifo, buffer, size, elemSize);
  return 1;
}

void kfifo_free(struct kfifo *fifo) {  // free resource
  free(fifo->buffer);
  fifo->index[17] = fifo->index[0] = fifo->index[34] = fifo->index[51] = 0;
  // fifo->buffer = NULL;
}

static inline unsigned int kfifo_avail_int(struct kfifo *fifo) {  // left space of fifo
    return fifo->index[34] - (fifo->index[17] - fifo->index[0]);
}

static inline unsigned int kfifo_in_data(struct kfifo *fifo, char *from) {
  unsigned int off_int = (fifo->index[17] & (fifo->index[34] - 1));  // next_in place, int
  unsigned int l = min(1, (fifo->index[34] - off_int));
  memcpy(fifo->buffer + off_int * fifo->index[51], from, l*fifo->index[51]);
  memcpy(fifo->buffer, from + l*fifo->index[51], (1 - l) * fifo->index[51]);
  if (fifo->buffer + off_int*fifo->index[51] == NULL) {  // if execute this in an unexpected order
    return 0;
  }
  return 1;
}

unsigned int kfifo_push(struct kfifo* fifo, char* buffer) {
  int len = min(kfifo_avail_int(fifo), 1);
  if (!kfifo_in_data(fifo, buffer)) {
    return 0;
  }
  fifo->index[17] += len;
  return len;
}

static inline unsigned int kfifo_out_data(struct kfifo *fifo, char *to) {
  unsigned int off = (fifo->index[0] & (fifo->index[34]-1));
  unsigned int l = min(1, (fifo->index[34] - off));
  memcpy(to, fifo->buffer + off * fifo->index[51], l*fifo->index[51]);
  memcpy(to + l*fifo->index[51], fifo->buffer, (1 - l)*fifo->index[51]);
  // char* p = fifo->buffer + off * fifo->index[51];
  // p = NULL;  // reset the out position as NULL
  return 1;
}

unsigned int kfifo_get(struct kfifo* fifo, char* buffer){
  int len = min(fifo->index[17] - fifo->index[0], 1);
  if (!kfifo_out_data(fifo, buffer)) {
    return 0;
  }
  fifo->index[0] += len;
  return len;
}

為了在 C++ 中使用它,我有一個包裝器:fifo_queue.h

#include "kfifo_ing.c"

template <typename T>
class FIFO_Queue {
 public:
  FIFO_Queue(int size) {
    kfifo_alloc(&k, size, sizeof(T));
  }
  ~FIFO_Queue() {
    // kfifo_free(&k);
  }
  bool push(const T& t) {
    return kfifo_push(&k, (char*)(&t));
  }

  bool pop(T& t) {
    return kfifo_get(&k, (char*)(&t));
  }
 private:
  kfifo k;
};

我已經測試了這個隊列,我認為當元素是簡單結構的 int 時它是正確的。

但是當結構具有 std::string 對象時會發生奇怪的事情,這是我的測試代碼:

#include "fifo_queue.h"
#include <string>
using namespace std;

struct huang {
  int a;
  string b;  // if dont have b, everything is good, but once add it, crashed!!!!!!!!
  double c;
  void Show(FILE* stream) const {
    fprintf(stream, "%d %lf\n", a, c); 
  }
};

FIFO_Queue<huang>q(80);

int main() {
  huang h;
  h.a = 1;
  q.push(h);
  q.pop(h);
  q.pop(h); // if no this, wont crash!!!!
  return 0;
}

代碼崩潰了,當我使用 gdb 檢查堆棧時,它警告我錯誤發生在 ~basic_string() 中,我很困惑,我知道 string 是一個復雜的設計數據結構,它有兩個指針。 但是有人能解釋一下嗎? 是雙免費造成的嗎? 有什么方法可以使它起作用嗎?

int main()
{
    huang h;
    h.a = 1;
    q.push(h);
    q.pop(h);
    q.pop(h); // if no this, wont crash!!!!
    return 0;
}

在您的代碼中,您只將 1 huang推到了q 但是你彈出兩次。 我懷疑您在第二次 pop 中放入h的內容在huang中沒有正確構造的string b 當您為h保留范圍hstring b會被破壞,並且可能會訪問不屬於您的進程的內存並因此而崩潰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM