gpt4 book ai didi

从 windows 和 mac 通过 ssh 编译和运行 C 程序 -- windows 出现 seg 错误

转载 作者:行者123 更新时间:2023-11-30 17:11:04 27 4
gpt4 key购买 nike

所以我有一个特定的 C 程序,当我编译和运行时,它可以在我的 Mac 上运行。我还在学校的linux计算机上通过ssh进行了测试,运行良好。然而,我的 friend 有一台PC,他使用PuTTY访问Linux计算机,并且使用完全相同的代码,他在运行程序时总是出现段错误。为什么会这样?

下面列出了代码。我已经提供了完整的代码,但是正如我们通过 print 语句发现的那样,问题在于主 block 早期的 int counter = 0; 行:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

typedef struct Nodes{
char firstName[40];
char lastName[40];
char townName[70];
struct Nodes* next;
} Node;

//-- create head global variable.
Node* head;

//-- check if a char array contains a dash (to check for the 9 digit zip code)
bool containsDash(char* string){
char *s;
s = strchr (string, '-');
if (s==NULL){
return false;
}
else{
return true;
}
}

//-- insert node after ptr, with given attributes.
void insertNodeAfter(Node* ptr, char* fName, char* lName, char* tName){
Node* newPtr = (Node*) malloc(sizeof(Node));
strcpy(newPtr->firstName, fName);
strcpy(newPtr->lastName, lName);
strcpy(newPtr->townName, tName);
newPtr->next = ptr->next;
ptr->next = newPtr;
}

//-- insert node before head.
Node* insertNodeBeforeHead(char* fName, char* lName, char* tName){
Node* ptr = (Node*) malloc(sizeof(Node));
strcpy(ptr->firstName, fName);
strcpy(ptr->lastName, lName);
strcpy(ptr->townName, tName);

ptr->next = head;
head = ptr;
return ptr;
}

//-- check if char array starts with start
bool startsWith(char *start, char *str){
size_t lenstart = strlen(start);
size_t lenstr = strlen(str);
if (lenstart > lenstr){
return false;
}
else{
return strncmp(start, str, lenstart) == 0;
}
}

//-- check if nodes have equal attributes.
bool nodesEqual(Node* first, Node* second){
if (strcmp(first->firstName, second->firstName) == 0 && strcmp(first->lastName, second->lastName) == 0 && strcmp(first->townName, second->townName) == 0){
return true;
}
else{
return false;
}
}

//-- delete ptr node
void deleteNode(Node* ptr){
if (nodesEqual(ptr, head)){
head = ptr->next;
free(ptr);
}
else{
Node* temp = head;
while(1){
if (nodesEqual(temp->next, ptr)){
temp->next = temp->next->next;
free(ptr);
break;
}
else{
temp = temp->next;
}
}
}
}

//-- delete node with the given first and last name
void deleteNodeByInfo(char* fName, char* lName){
if (head == NULL){
return;
}
Node* temp = head;
while(1){
if (strcmp(temp->firstName, fName) == 0 && strcmp(temp->lastName, lName) == 0){
deleteNode(temp);
break;
}
if (temp->next != NULL){
temp = temp->next;
}
else{
break;
}
}
}

//-- take the current attributes and make a node in the correct spot
void insertNodeInCorrectSpot(char* fName, char* lName, char* tName){
//-- take 2 pointers separated by one link, look for a spot to insert node between these pointers
Node* pointer = head;
Node* pointer2 = head;
if (pointer->next != NULL){
pointer2 = pointer2->next;
}
else{
pointer2 = pointer2->next;
}
if (strcmp(tName, pointer->townName) < 0){
Node* newHead = insertNodeBeforeHead(fName, lName, tName);
head = newHead;
}
else{
while(strcmp(tName, pointer2->townName) > 0){
if (pointer2->next != NULL){
pointer = pointer->next;
pointer2 = pointer2->next;
}
else{
pointer = pointer2;
break;
}
}
insertNodeAfter(pointer, fName, lName, tName);
}
}

//-- remove spaces at the end of a string
void removeSpacesAtEnd(char* input){
int end = strlen(input) - 1;
if (isspace(input[end])){
input[end] = '\0';
}
if (isspace(input[--end])){
removeSpacesAtEnd(input);
}
}

//-- print the attributes of a given node
void printNode(Node* pointer){
printf("%s", pointer->firstName);
// printf("%s", " ");
printf("%s", pointer->lastName);
// printf("%s", " ");
printf("%s\n", pointer->townName);
}

// -d is option for debug.

int main(int argc, char* argv[]){
int counter = 0; //-- keep counter to keep track of cycle
char *tempChar, *tempFName, *tempLName, *tempTName;

//-- create buffers to store first name, last name, town name
tempChar = (char*)malloc(100*sizeof(char));
tempFName = (char*)malloc(40*sizeof(char));
tempLName = (char*)malloc(40*sizeof(char));
tempTName = (char*)malloc(70*sizeof(char));
while(counter < 600){
fgets(tempChar, 100, stdin);
//-- remove newline delimiter
char *pos;
if ((pos=strchr(tempChar, '\n')) != NULL)
*pos = '\0';
//-- The text will always go in a cycle of 6. Use modular division to figure out what is in the line being read.
if (counter % 6 == 0){
strncpy(tempFName, tempChar, strlen(tempChar));
removeSpacesAtEnd(tempFName);
strcat(tempFName, " ");
}
else if (counter % 6 == 1){
strncpy(tempLName, tempChar, strlen(tempChar));
removeSpacesAtEnd(tempLName);
if (counter == 1){
size_t len = strlen(tempChar);
tempLName[len] = '\0';
}
strcat(tempLName, " ");
}
else if (counter % 6 == 3){
if (containsDash(tempChar)){
strncpy(tempTName, tempChar, strlen(tempChar)-15);
}
else{
strncpy(tempTName, tempChar, strlen(tempChar)-9);
}
removeSpacesAtEnd(tempTName);
strcat(tempTName, " ");
}
else if (counter % 6 == 4){
if (counter == 4){
head = (Node*) malloc(sizeof(Node));
strcpy(head->firstName, tempFName);
strcpy(head->lastName, tempLName);
strcpy(head->townName, tempTName);
}
else{
insertNodeInCorrectSpot(tempFName, tempLName, tempTName);
}
memset(tempFName, 0, strlen(tempFName));
memset(tempLName, 0, strlen(tempLName));
memset(tempTName, 0, strlen(tempTName));
}
memset(tempChar, 0, strlen(tempChar));
counter++;
}
}

最佳答案

我不知道这是否是你 friend 遇到的同样的问题。但是在添加了 stdbool.h 后,我可以通过像这样运行它来在我的 mac 上获得段错误:

$ ./testit < /etc/group

这里出了问题:

//-- remove spaces at the end of a string
void removeSpacesAtEnd(char* input){
int end = strlen(input) - 1;
if (isspace(input[end])){
input[end] = '\0';
}
if (isspace(input[--end])){
removeSpacesAtEnd(input);
}
}

输入错误:

"# Note that this file is consulted directly only when the system i"

该行倒数第二个位置包含空格,但最后一个位置不包含空格。这会导致 removeSpacesAtEnd() 函数无限递归,直到填满调用堆栈。

最简单的修复方法是将第二个“if” block 移到第一个“if” block 内,这样它仅在输入的最后一个字符是空格时执行:

//-- remove spaces at the end of a string
void removeSpacesAtEnd(char* input){
int end = strlen(input) - 1;
if (isspace(input[end])){
input[end] = '\0';
if (isspace(input[--end])){
removeSpacesAtEnd(input);
}
}
}

修复该问题后,程序现在在这里崩溃:

    else if (counter % 6 == 3){
if (containsDash(tempChar)){
strncpy(tempTName, tempChar, strlen(tempChar)-15);
}
else{
strncpy(tempTName, tempChar, strlen(tempChar)-9); <-- Here
}

所以,这个程序可能还有其他问题。

您应该学习如何使用调试器。这真的不难,而且会节省你很多令人沮丧的时间。以下是我如何使用 OSX 调试器 lldb 来找出第二次崩溃:

使用调试符号(-g)编译程序:

$ gcc -g -o testit testit.c
$

在“testit”程序上调用调试器。在 Linux 上,您可以使用 gdb 而不是 lldb,但我将在此处使用的命令是相同的。

$ lldb testit
(lldb) target create "testit"
Current executable set to 'testit' (x86_64).
(lldb)

运行“testit

(lldb) run < /etc/group
Process 40951 launched: '/Users/kherron/x/testit' (x86_64)
Process 40951 stopped
* thread #1: tid = 0xc882f9, 0x00007fff8bde3c69 libsystem_platform.dylib`_platform_bzero$VARIANT$Unknown + 41, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x100200000)
frame #0: 0x00007fff8bde3c69 libsystem_platform.dylib`_platform_bzero$VARIANT$Unknown + 41
libsystem_platform.dylib`_platform_bzero$VARIANT$Unknown:
-> 0x7fff8bde3c69 <+41>: rep
0x7fff8bde3c6a <+42>: stosb %al, %es:(%rdi)
0x7fff8bde3c6b <+43>: movq %rdx, %rax
0x7fff8bde3c6e <+46>: popq %rbp
(lldb)

是的,这对我来说也是官样文章。别担心。让我们看看这里的函数调用堆栈。 “bt”是“backtrace”,打印调用堆栈。

(lldb) bt
* thread #1: tid = 0xc882f9, 0x00007fff8bde3c69 libsystem_platform.dylib`_platform_bzero$VARIANT$Unknown + 41, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x100200000)
* frame #0: 0x00007fff8bde3c69 libsystem_platform.dylib`_platform_bzero$VARIANT$Unknown + 41
frame #1: 0x00007fff8e90e40d libsystem_c.dylib`stpncpy + 70
frame #2: 0x00007fff8e980f12 libsystem_c.dylib`__strncpy_chk + 38
frame #3: 0x0000000100001c20 testit`main(argc=1, argv=0x00007fff5fbffb70) + 752 at testit.c:201
frame #4: 0x00007fff8b56c5c9 libdyld.dylib`start + 1
(lldb)

第 3 帧看起来像程序中的一行。我们来看看。

(lldb) up 3
frame #3: 0x0000000100001c20 testit`main(argc=1, argv=0x00007fff5fbffb70) + 752 at testit.c:201
198 strncpy(tempTName, tempChar, strlen(tempChar)-15);
199 }
200 else{
-> 201 strncpy(tempTName, tempChar, strlen(tempChar)-9);
202 }
203 removeSpacesAtEnd(tempTName);
204 strcat(tempTName, " ");

好的,打印当时tempChar的值。

(lldb) p tempChar
(char *) $0 = 0x0000000100104b80 "##"

为了清楚地说明这一点,请打印出表达式“strlen(tempChar)-9”的值:

(lldb) p strlen(tempChar) - 9
error: 'strlen' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression
(lldb) p (int)(strlen(tempChar)) - 9
(int) $1 = -7

因此,它将负长度传递给 strlen()。

关于从 windows 和 mac 通过 ssh 编译和运行 C 程序 -- windows 出现 seg 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32547313/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com