首页 > 解决方案 > 这个子字符串在 C 中安全吗?

问题描述

我需要从不同长度的字符串中提取子字符串。我想避免使用malloc。

这安全吗?

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

int main()
{   
    const char *PATTERN1 = "<Abcd.";
    const char *PATTERN2 = ">";
    const char *PATTERN3 = "<Fghi.";
    char *begin, *end;

    int len;
    char result[50];
    // lenght of toFind could be different i.e. "<Abcd.toGet>" or "<Abcd.toGettoGettoGet>" always less than 50
    char *toFind[50] = {"<Abcd.toGettoGet>","<Abcd.toGettoGetoGet>","<Abcd.toGet>"}; 
    
    int element = 3;
    int i = 0;
    for (i = 0; i < element ; i++) {

    begin = strstr(toFind[i], PATTERN1);
    printf("Begin: %s \n", begin); 
    
    if (begin == NULL) {
        perror("Null begin\n");
    }
    
    begin += strlen(PATTERN1);
    printf("Begin2: %s \n", begin);
    end = strstr(begin, PATTERN2);
    printf("End: %s \n", end); 
    
    if (end == NULL) {
        perror("Null end\n");
    }
    len = end - begin;
    printf("Len: %d \n", len); 

    strncpy(result, begin, len);
    result[len] = '\0';
    
    printf("Result = %s\n",result);
    
    sleep(5);
    }
        
    return 0;
}

我想知道这是否是一种正确且安全的方法,以避免分段错误或内存损坏/泄漏。尤其是 *begin 和 *end 它是如何初始化的。

标签: cpointersmemory-leakssubstringstrncpy

解决方案


您需要解决一些问题。

  1. 不要只在beginorend为 NULL 时继续。

else您应该在放置以下代码的位置添加一个部分。例子:

if (begin == NULL) {
    perror("Null begin\n");
} else {
    begin += strlen(PATTERN1);
    ...
    ...
    if (end == NULL) {
        perror("Null end\n");
    } else {
        len = end - begin;
        ...
        ...
    }
}
  1. 考虑写作result越界。

result数组是固定大小的,但len可以得到任何大小。所以使用strncpy(result, begin, len);不会保护你免受越界写入。使用前添加检查strncpy

  1. 如果strstr返回 NULL,则不打印字符串。

IE

begin = strstr(toFind[i], PATTERN1);
printf("Begin: %s \n", begin);   // Check for NULL **before** printing

推荐阅读