我有以下头文件:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
/** **/
// size: 1B
typedef enum string_proc_func_type_t{
REVERSIBLE = 0,
IRREVERSIBLE = 1
} __attribute__((__packed__)) string_proc_func_type;
// size: 12B
typedef struct string_proc_key_t {
uint32_t length; // 4B
char* value; // 8B (ptr)
} __attribute__((__packed__)) string_proc_key;
typedef void (*string_proc_func) (string_proc_key*);
// size 24B
typedef struct string_proc_list_t {
char* name; // 8B (ptr)
struct string_proc_node_t* first; // 8B (ptr)
struct string_proc_node_t* last; // 8B (ptr)
} __attribute__((__packed__)) string_proc_list;
// size 33B
typedef struct string_proc_node_t {
struct string_proc_node_t* next; // 8B (ptr)
struct string_proc_node_t* previous; // 8B (ptr)
string_proc_func f; // 8B (ptr)
string_proc_func g; // 8B (ptr)
string_proc_func_type type; // 1B
} __attribute__((__packed__)) string_proc_node;
string_proc_list* string_proc_list_create(char* name);
void string_proc_list_destroy(string_proc_list* list);
// Aux functions
uint32_t str_len(char* a);
char* str_copy(char* a);
我已经实现了如下的辅助功能:
uint32_t str_len(char* a) {
uint32_t cont = 0;
while(a != NULL && *a != '\0') {
cont++;
a++;
}
return cont;
}
char* str_copy(char* a) {
uint32_t length = str_len(a);
char* copy = malloc(length);
for (uint32_t i = 0; i < length; ++i) {
copy[i] = a[i];
}
return copy;
}
现在我想在Assembly上实现string_proc_list_create
函数,我最终得到了这个:
; C functions
extern malloc
extern free
extern fopen
extern fclose
extern fprintf
extern str_copy
; structs sizes
%define STRUCT_STRING_PROC_LIST_SIZE 24
; structs offsets
%define STRUCT_STRING_PROC_LIST_NAME_OFFSET 0
%define STRUCT_STRING_PROC_LIST_FIRST_OFFSET 8
%define STRUCT_STRING_PROC_LIST_LAST_OFFSET 16
section .data
section .text
global string_proc_list_create
string_proc_list_create:
push rbp
mov rbp, rsp
push rdi ; save ptr to name
; allocate mem for struct
mov rdi, STRUCT_STRING_PROC_LIST_SIZE
sub rsp, 8 ; align stack
call malloc
add rsp, 8 ; unalign stack
; get ptr to struct at RAX
pop rdi ; get ptr to name en RDI
; save ptr to struct at RBX
push rbx
mov rbx, rax
; copy name
add rsp, 8 ; align stack
call str_copy
add rsp, 8 ; unalign stack
; get ptr to name (copy) at RAX
; initialize struct (ptr to struct at RBX, ptr to name (copy) at RAX)
mov qword [rbx + STRUCT_STRING_PROC_LIST_NAME_OFFSET], rax
mov qword [rbx + STRUCT_STRING_PROC_LIST_FIRST_OFFSET], 0
mov qword [rbx + STRUCT_STRING_PROC_LIST_LAST_OFFSET], 0
pop rbx
pop rbp
ret
然后,我尝试执行这一行:
string_proc_list* list = string_proc_list_create("aName");
但我在RET处遇到了分段错误。我认为我可能会破坏堆栈框架,但我无法找到代码的错误。有什么帮助吗?
答案 0 :(得分:0)
问题不在您发布的代码中,这是完全正确的(如果您说的是您的意思),但很可能是您使用str_copy
的地方。问题是你得到一个非空终止字符串的字符串。你
uint32_t length = str_len(a);
char* copy = malloc(length);
当您必须malloc(length+1);
允许最终\0
个字符时。
然后,您将长度字符从原始字符串复制到副本。然后你应该在字符串中添加一个最终的\0
字符,这样它就完成了。
您的代码没有问题,但它不会生成字符串,而是生成包含原始字符串有价值内容的char数组。要使它成为一个合适的字符串,你需要为null char获取空间,并将其添加到字符串中,如下所示:
char* str_copy(char* a) {
uint32_t length_plus_1 = str_len(a) + 1; // enough for null to be included
char* copy = malloc(length_plus_1);
for (uint32_t i = 0; i < length_plus_1; ++i) {
copy[i] = a[i];
}
return copy;
}