使用Intel Intrinsics对比字符串返回结果不符合预期的问题求助
问题原因
1. 越界访问触发未定义行为
你定义的字符串常量const char * value = "GET "仅占用5字节内存(4个有效字符+1个终止符),直接调用_mm_loadu_si128从该地址读取16字节属于非法访问,u_str后12字节是内存随机垃圾值,直接导致比较结果完全不符合预期,这是返回值恒为1的核心原因。
2. SSE4.2比较指令配置错误
_mm_cmpestrc的立即数需要完整指定三类配置:数据类型、比较模式、结果聚合模式,你的代码仅配置了前两项,缺少聚合模式标识,指令实际执行的聚合逻辑和你预期的「判断4个字符是否全部相等」完全不符。同时你对该指令返回值的含义理解错误,默认配置下返回1代表存在至少一个字符不相等,返回0才代表全部匹配。
修复方案
推荐优先用更通用的SIMD逐字节比较方案,无需记忆SSE4.2字符串指令的复杂参数,出错概率更低:
void parse_with_simd(const char *buffer, const int buffer_len) { // 先做边界检查,避免短缓冲区越界 if (buffer_len < 4) { debug_print("has value 1\n"); return; } // 小端模式下 "GET " 对应的32位常量,直接构造避免字符串加载越界 const uint32_t get_prefix = 0x20544547; __m128i target = _mm_set1_epi32(get_prefix); __m128i loaded = _mm_loadu_si128((const __m128i *)buffer); // 逐字节比较后提取掩码 __m128i eq_mask = _mm_cmpeq_epi8(target, loaded); int bit_mask = _mm_movemask_epi8(eq_mask); // 低4位全1代表前4字节完全匹配 int not_equal = (bit_mask & 0xf) != 0xf; debug_print("has value %d\n", not_equal); }
修复后测试:
- 第一个用例
"GET / HTTP/1.1"匹配前缀,返回0 - 第二个用例
"OPTIONS /"不匹配前缀,返回1
符合预期。
如果你坚持用SSE4.2字符串比较指令,需要修正常量加载和控制位配置:
void parse_with_simd(const char *buffer, const int buffer_len) { if (buffer_len < 4) { debug_print("has value 1\n"); return; } // 用16字节数组存储比较常量,避免加载越界 const char target_arr[16] = "GET "; __m128i u_str = _mm_loadu_si128((const __m128i *)target_arr); __m128i loaded = _mm_loadu_si128((const __m128i *)buffer); // 补全聚合模式配置,明确返回值逻辑 int not_equal = _mm_cmpestrc(loaded, 4, u_str, 4, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY); debug_print("has value %d\n", not_equal); }
内容的提问来源于stack exchange,提问作者Christopher Clark
相关产品推荐
相关产品推荐

