linux下使用valgrind排查内存泄漏

news/2024/12/22 17:29:08/

安装

yum install valgrind -y

说明

1)概念

Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。Valgrind包括memcheck、Callgrind、Cachegrind、Helgrind、Massif等工具。memcheck用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc()/free()/new/delete 的调用都会被捕获。

2)命令行

valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --undef-value-errors=no --log-file=log ./可执行程序名
  • –tool=memcheck:使用 memcheck 工具检测内存错误,包括使用未初始化的变量、读写越界等;
  • –leak-check=full:全面检测内存泄漏,不仅仅检测未释放的内存,还会检测处理时出现的一些问题;
  • –show-leak-kinds=all:显示所有的内存泄漏信息;
  • –undef-value-errors=no:不检查未定义的值错误;
  • –log-file=log:将日志信息输出到 log 文件中;

几种内存问题

申请内存多次释放

示例

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;void MyTest()
{char* p = (char*)malloc(sizeof(char)*10);delete[] p;cout << "MyTest finished" << endl;delete[] p;
}int main()
{MyTest();return 0;
}

测试

执行valgrind --leak-check=yes ./testValgrind查看结果。

[root@localhost debug]# valgrind --leak-check=yes ./testValgrind
==5532== Memcheck, a memory error detector
==5532== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5532== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==5532== Command: ./testValgrind
==5532== 
==5532== Mismatched free() / delete / delete []
==5532==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==5532==    by 0x400A1A: MyTest() (testValgrind.cpp:10)
==5532==    by 0x400A64: main (testValgrind.cpp:19)
==5532==  Address 0x6b529d0 is 0 bytes inside a block of size 10 alloc'd
==5532==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==5532==    by 0x400A03: MyTest() (testValgrind.cpp:8)
==5532==    by 0x400A64: main (testValgrind.cpp:19)
==5532== 
MyTest finished
==5532== Invalid free() / delete / delete[] / realloc()
==5532==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==5532==    by 0x400A58: MyTest() (testValgrind.cpp:14)
==5532==    by 0x400A64: main (testValgrind.cpp:19)
==5532==  Address 0x6b529d0 is 0 bytes inside a block of size 10 free'd
==5532==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==5532==    by 0x400A1A: MyTest() (testValgrind.cpp:10)
==5532==    by 0x400A64: main (testValgrind.cpp:19)
==5532==  Block was alloc'd at
==5532==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==5532==    by 0x400A03: MyTest() (testValgrind.cpp:8)
==5532==    by 0x400A64: main (testValgrind.cpp:19)
==5532== 
==5532== 
==5532== HEAP SUMMARY:
==5532==     in use at exit: 32 bytes in 1 blocks
==5532==   total heap usage: 22 allocs, 22 frees, 136,124 bytes allocated
==5532== 
==5532== LEAK SUMMARY:
==5532==    definitely lost: 0 bytes in 0 blocks
==5532==    indirectly lost: 0 bytes in 0 blocks
==5532==      possibly lost: 0 bytes in 0 blocks
==5532==    still reachable: 32 bytes in 1 blocks
==5532==         suppressed: 0 bytes in 0 blocks
==5532== Reachable blocks (those to which a pointer was found) are not shown.
==5532== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==5532== 
==5532== For lists of detected and suppressed errors, rerun with: -s
==5532== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
[root@localhost debug]# 

结果分析:

# 不匹配的free,(testValgrind.cpp:10)进行了
==5532== Mismatched free() / delete / delete []
==5532==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==5532==    by 0x400A1A: MyTest() (testValgrind.cpp:10)
==5532==    by 0x400A64: main (testValgrind.cpp:19)
==5532==  Address 0x6b529d0 is 0 bytes inside a block of size 10 alloc'd
==5532==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==5532==    by 0x400A03: MyTest() (testValgrind.cpp:8)
==5532==    by 0x400A64: main (testValgrind.cpp:19)
==5532== 

内存泄漏

示例

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;void MyTest()
{char* p = (char*)malloc(sizeof(char)*10);cout << &p << endl;
}int main()
{MyTest();return 0;
}

测试

执行valgrind --leak-check=yes ./testValgrind查看结果。

[root@localhost debug]# valgrind --leak-check=yes ./testValgrind
==12941== Memcheck, a memory error detector
==12941== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12941== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==12941== Command: ./testValgrind
==12941== 
0x1ffefff8a8
==12941== 
==12941== HEAP SUMMARY:
==12941==     in use at exit: 42 bytes in 2 blocks
==12941==   total heap usage: 22 allocs, 20 frees, 136,124 bytes allocated
==12941== 
==12941== 10 bytes in 1 blocks are definitely lost in loss record 1 of 2
==12941==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==12941==    by 0x400993: MyTest() (testValgrind.cpp:8)
==12941==    by 0x4009CE: main (testValgrind.cpp:15)
==12941== 
==12941== LEAK SUMMARY:
==12941==    definitely lost: 10 bytes in 1 blocks
==12941==    indirectly lost: 0 bytes in 0 blocks
==12941==      possibly lost: 0 bytes in 0 blocks
==12941==    still reachable: 32 bytes in 1 blocks
==12941==         suppressed: 0 bytes in 0 blocks
==12941== Reachable blocks (those to which a pointer was found) are not shown.
==12941== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==12941== 
==12941== For lists of detected and suppressed errors, rerun with: -s
==12941== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
[root@localhost debug]# 

结果分析:

# 10个字节确定丢失,发生了内存泄漏
==12941== 10 bytes in 1 blocks are definitely lost in loss record 1 of 2
==12941==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==12941==    by 0x400993: MyTest() (testValgrind.cpp:8)
==12941==    by 0x4009CE: main (testValgrind.cpp:15)
==12941== # 总结摘要部分也可确认该问题
==12941== LEAK SUMMARY:
==12941==    definitely lost: 10 bytes in 1 blocks   --- 确定发生了10个字节的内存泄漏
==12941==    indirectly lost: 0 bytes in 0 blocks
==12941==      possibly lost: 0 bytes in 0 blocks
==12941==    still reachable: 32 bytes in 1 blocks
==12941==         suppressed: 0 bytes in 0 blocks
==12941== Reachable blocks (those to which a pointer was found) are not shown.
==12941== To see them, rerun with: --leak-check=full --show-leak-kinds=all

释放空指针

示例

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;int main()
{char* p = nullptr;bool bFind = false;// ... // 此时bFind仍为falseif(bFind){p = new char[64];}delete[] p;return 0;
}

测试

执行valgrind --leak-check=yes ./testValgrind查看结果。

[root@localhost debug]# valgrind --leak-check=yes ./testValgrind
==23591== Memcheck, a memory error detector
==23591== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==23591== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==23591== Command: ./testValgrind
==23591== 
==23591== 
==23591== HEAP SUMMARY:
==23591==     in use at exit: 32 bytes in 1 blocks
==23591==   total heap usage: 21 allocs, 20 frees, 136,114 bytes allocated
==23591== 
==23591== LEAK SUMMARY:
==23591==    definitely lost: 0 bytes in 0 blocks
==23591==    indirectly lost: 0 bytes in 0 blocks
==23591==      possibly lost: 0 bytes in 0 blocks
==23591==    still reachable: 32 bytes in 1 blocks
==23591==         suppressed: 0 bytes in 0 blocks
==23591== Reachable blocks (those to which a pointer was found) are not shown.
==23591== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==23591== 
==23591== For lists of detected and suppressed errors, rerun with: -s
==23591== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[root@localhost debug]# 

申请与释放的内存不匹配

示例

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;int main()
{char* p = new char[20];for(int i = 0; i < 20; i++){cout << *(p++) << endl;}delete[] p;return 0;
}

测试

执行valgrind --leak-check=yes ./testValgrind查看结果。

[root@localhost debug]# valgrind --leak-check=yes ./testValgrind
==26240== Memcheck, a memory error detector
==26240== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==26240== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==26240== Command: ./testValgrind
==26240== 
==26240== Conditional jump or move depends on uninitialised value(s)
==26240==    at 0x65C8F6E: _IO_file_overflow@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.so)
==26240==    by 0x65CA030: _IO_default_xsputn (in /usr/lib64/libc-2.17.so)
==26240==    by 0x65C7A91: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.so)
==26240==    by 0x65BC7E1: fwrite (in /usr/lib64/libc-2.17.so)
==26240==    by 0x4ECDBB4: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (in /usr/lib64/libstdc++.so.6.0.19)
==26240==    by 0x4ECDDE7: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char) (in /usr/lib64/libstdc++.so.6.0.19)
==26240==    by 0x400A37: main (testValgrind.cpp:12)
==26240== 
==26240== Syscall param write(buf) points to uninitialised byte(s)
==26240==    at 0x663CBA0: __write_nocancel (in /usr/lib64/libc-2.17.so)
==26240==    by 0x65C72F2: _IO_file_write@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.so)
==26240==    by 0x65C8B0D: _IO_do_write@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.so)
==26240==    by 0x65C9002: _IO_file_overflow@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.so)
==26240==    by 0x65C4BD8: putc (in /usr/lib64/libc-2.17.so)
==26240==    by 0x4ECD5C5: std::ostream::put(char) (in /usr/lib64/libstdc++.so.6.0.19)
==26240==    by 0x4ECD811: std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) (in /usr/lib64/libstdc++.so.6.0.19)
==26240==    by 0x400A4C: main (testValgrind.cpp:12)
==26240==  Address 0x4023000 is in a rw- anonymous segment
==26240== ==26240== Conditional jump or move depends on uninitialised value(s)
==26240==    at 0x65C7AE5: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.so)
==26240==    by 0x65BC7E1: fwrite (in /usr/lib64/libc-2.17.so)
==26240==    by 0x4ECDBB4: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (in /usr/lib64/libstdc++.so.6.0.19)
==26240==    by 0x4ECDDE7: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char) (in /usr/lib64/libstdc++.so.6.0.19)
==26240==    by 0x400A37: main (testValgrind.cpp:12)
==26240== ==26240== Invalid free() / delete / delete[] / realloc()
==26240==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==26240==    by 0x400A65: main (testValgrind.cpp:15)
==26240==  Address 0x6b529e4 is 0 bytes after a block of size 20 alloc'd
==26240==    at 0x4C2AC38: operator new[](unsigned long) (vg_replace_malloc.c:433)
==26240==    by 0x400A03: main (testValgrind.cpp:8)
==26240== 
==26240== 
==26240== HEAP SUMMARY:
==26240==     in use at exit: 52 bytes in 2 blocks
==26240==   total heap usage: 22 allocs, 21 frees, 136,134 bytes allocated
==26240== 
==26240== 20 bytes in 1 blocks are definitely lost in loss record 1 of 2
==26240==    at 0x4C2AC38: operator new[](unsigned long) (vg_replace_malloc.c:433)
==26240==    by 0x400A03: main (testValgrind.cpp:8)
==26240== 
==26240== LEAK SUMMARY:
==26240==    definitely lost: 20 bytes in 1 blocks
==26240==    indirectly lost: 0 bytes in 0 blocks
==26240==      possibly lost: 0 bytes in 0 blocks
==26240==    still reachable: 32 bytes in 1 blocks
==26240==         suppressed: 0 bytes in 0 blocks
==26240== Reachable blocks (those to which a pointer was found) are not shown.
==26240== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==26240== 
==26240== Use --track-origins=yes to see where uninitialised values come from
==26240== For lists of detected and suppressed errors, rerun with: -s
==26240== ERROR SUMMARY: 42 errors from 5 contexts (suppressed: 0 from 0)
[root@localhost debug]# 

结果分析:

# 关于“Conditional jump or move depends on uninitialised value(s)”
某些变量未初始化,检查一下数组/class/struct有没有赋初值,或者说看看初始化的大小是否为正确的大小,下面信息会提示在哪个函数里面。# 关于“Syscall param write(buf) points to uninitialised byte”
系统调用传递不可访问或未初始化内存。
# 需确认以下几点:
## 1. 参数是否有初始化
## 2. 如果是系统调用读取程序提供的buffer,会产检整个buffer是否可访问和已经初始化
## 3. 如果是系统调用要往用户的buffer写入数据,会检查buffer是否可访问# 在(testValgrind.cpp:15)处存在非法释放
==26240== Invalid free() / delete / delete[] / realloc()
==26240==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==26240==    by 0x400A65: main (testValgrind.cpp:15)
==26240==  Address 0x6b529e4 is 0 bytes after a block of size 20 alloc'd
==26240==    at 0x4C2AC38: operator new[](unsigned long) (vg_replace_malloc.c:433)
==26240==    by 0x400A03: main (testValgrind.cpp:8)
==26240== # 存在内存泄漏
==26240== LEAK SUMMARY:
==26240==    definitely lost: 20 bytes in 1 blocks  --- 存在20字节内存泄漏
==26240==    indirectly lost: 0 bytes in 0 blocks
==26240==      possibly lost: 0 bytes in 0 blocks
==26240==    still reachable: 32 bytes in 1 blocks
==26240==         suppressed: 0 bytes in 0 blocks

引用已释放的内存块

示例

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;int main()
{char* p = new char[20];// ...	delete[] p;// ... p[0] = 'a';return 0;
}

测试

执行valgrind --leak-check=yes ./testValgrind查看结果。

[root@localhost debug]# valgrind --leak-check=yes ./testValgrind
==38628== Memcheck, a memory error detector
==38628== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==38628== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==38628== Command: ./testValgrind
==38628== 
==38628== Invalid write of size 1
==38628==    at 0x4008AF: main (testValgrind.cpp:16)
==38628==  Address 0x6b529d0 is 0 bytes inside a block of size 20 free'd
==38628==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==38628==    by 0x4008AA: main (testValgrind.cpp:12)
==38628==  Block was alloc'd at
==38628==    at 0x4C2AC38: operator new[](unsigned long) (vg_replace_malloc.c:433)
==38628==    by 0x400893: main (testValgrind.cpp:8)
==38628== 
==38628== 
==38628== HEAP SUMMARY:
==38628==     in use at exit: 32 bytes in 1 blocks
==38628==   total heap usage: 22 allocs, 21 frees, 136,134 bytes allocated
==38628== 
==38628== LEAK SUMMARY:
==38628==    definitely lost: 0 bytes in 0 blocks
==38628==    indirectly lost: 0 bytes in 0 blocks
==38628==      possibly lost: 0 bytes in 0 blocks
==38628==    still reachable: 32 bytes in 1 blocks
==38628==         suppressed: 0 bytes in 0 blocks
==38628== Reachable blocks (those to which a pointer was found) are not shown.
==38628== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==38628== 
==38628== For lists of detected and suppressed errors, rerun with: -s
==38628== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
[root@localhost debug]# 

结果分析:

动态内存越界

# ==38628==在(testValgrind.cpp:16)处发生动态内存越界
==38628== Invalid write of size 1
==38628==    at 0x4008AF: main (testValgrind.cpp:16)
==38628==  Address 0x6b529d0 is 0 bytes inside a block of size 20 free'd
==38628==    at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==38628==    by 0x4008AA: main (testValgrind.cpp:12)
==38628==  Block was alloc'd at
==38628==    at 0x4C2AC38: operator new[](unsigned long) (vg_replace_malloc.c:433)
==38628==    by 0x400893: main (testValgrind.cpp:8)
==38628== 

越界访问

示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;void MyTest()
{char* p = new char[10];memset(p, 0, sizeof(char)*10);p[10] = 'c';	delete[] p;
}int main()
{MyTest();return 0;
}

测试

[root@localhost debug]# valgrind --leak-check=yes ./testValgrind
==44390== Memcheck, a memory error detector
==44390== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==44390== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==44390== Command: ./testValgrind
==44390== 
==44390== Invalid write of size 1
==44390==    at 0x400906: MyTest() (testValgrind.cpp:12)
==44390==    by 0x400927: main (testValgrind.cpp:19)
==44390==  Address 0x6b529da is 0 bytes after a block of size 10 alloc'd
==44390==    at 0x4C2AC38: operator new[](unsigned long) (vg_replace_malloc.c:433)
==44390==    by 0x4008E3: MyTest() (testValgrind.cpp:9)
==44390==    by 0x400927: main (testValgrind.cpp:19)
==44390== 
==44390== 
==44390== HEAP SUMMARY:
==44390==     in use at exit: 32 bytes in 1 blocks
==44390==   total heap usage: 22 allocs, 21 frees, 136,124 bytes allocated
==44390== 
==44390== LEAK SUMMARY:
==44390==    definitely lost: 0 bytes in 0 blocks
==44390==    indirectly lost: 0 bytes in 0 blocks
==44390==      possibly lost: 0 bytes in 0 blocks
==44390==    still reachable: 32 bytes in 1 blocks
==44390==         suppressed: 0 bytes in 0 blocks
==44390== Reachable blocks (those to which a pointer was found) are not shown.
==44390== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==44390== 
==44390== For lists of detected and suppressed errors, rerun with: -s
==44390== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
[root@localhost debug]# 

结果分析:

# 在(testValgrind.cpp:12)处程序访问非法地址的内存,无效写入,即堆溢出。
==44390== Invalid write of size 1
==44390==    at 0x400906: MyTest() (testValgrind.cpp:12)
==44390==    by 0x400927: main (testValgrind.cpp:19)
==44390==  Address 0x6b529da is 0 bytes after a block of size 10 alloc'd
==44390==    at 0x4C2AC38: operator new[](unsigned long) (vg_replace_malloc.c:433)
==44390==    by 0x4008E3: MyTest() (testValgrind.cpp:9)
==44390==    by 0x400927: main (testValgrind.cpp:19)
==44390== 

http://www.ppmy.cn/news/926497.html

相关文章

Unity自定义后处理——Vignette暗角

大家好&#xff0c;我是阿赵。   继续说一下屏幕后处理的做法&#xff0c;这一期讲的是Vignette暗角效果。 一、Vignette效果介绍 Vignette暗角的效果可以给画面提供一个氛围&#xff0c;或者模拟一些特殊的效果。 还是拿这个角色作为底图 添加了Vignette效果后&#xff0…

Android上的skype

传说Skype要单飞了&#xff0c;不错&#xff0c;作为其忠实用户&#xff0c;还是比较看好它的发展的&#xff0c;当然在中国除外&#xff0c;天朝的儿子移动和联通肯定是不会放过他的。而Skype在移动设备上的发展还算比较顺利&#xff0c;wm上的skype以前用的很high&#xff0c…

教你如何使用iPhone上MSN,聊Skype

<script languagejavascript srchttp://www.shiqiaotou.com/donetk/Header.js></script> Web MSN 不稀奇&#xff0c;iPhone 专用的才特別&#xff0c;在iPhone上也能用MSN&#xff0c;这下您又多添加一条买支iPhone的理由了&#xff01; 使用方法&#xff1a; 用…

Mac添加Skype For Business麦克风权限/Skype For Business麦克风没有声音(终端添加)亲测好用!!!!!

公司需要安装Skype For Business办公,在Mac系统安装的时候突然发现麦克风没有声音,一看在权限中也不显示 查找网上各种解决方案都不好用,最后通过终端直接添加的方式解决了,话不多说下面上干货 1.重启动Mac&#xff0c;并按住commanr&#xff0c;进入恢复模式 2.打开终端(Term…

罪犯用 Skype 躲避警察

最近&#xff0c;意大利警方对Skype网络电话可以说是恨之入骨&#xff0c;很多人都会纳闷&#xff0c;Skype做的是网络电话&#xff0c; 怎么会惹着意大利的警察呢&#xff1f;有些东西就是很奇怪&#xff0c; 做的太好了反而会招惹一些是非。现在&#xff0c;一些贩毒、军火走…

Microsoft 365自定义安装,卸载Access、Publisher、Skype

买电脑送的Office 2019只有Word、Excel、PowerPoint三件套&#xff0c;一般情况都是够用的&#xff0c;可以前往Microsoft 帐户 | 服务和订阅中下载一键安装。 但是拥有Microsoft 365&#xff08;原Office 365&#xff09;用户&#xff0c;一键安装会被强制安装很多用不上的软件…

微软证实将用Skype替换MSN服务

微软证实将用Skype替换MSN服务 北京时间11月7日消息&#xff0c;微软周二正式宣布&#xff0c;Windows Live Messenger服务将在2013年第一季度中停止使用。微软表示&#xff0c;作为这项举措的部分内容&#xff0c;该公司将把1亿多名Messenger用户(微软在周二向 科技博客网站Th…

网页中插入Skype链接标签 ,参数大全

这两天我们看了不少关于标签的知识。除了利用提供的网页来生成标签外&#xff0c;你也可以通过如下方法实现标签的高级功能。 使用链接 你可以把链接放入到HTML代码中&#xff0c;这样别人在打开页面后就能方便的联系你。缺省情况下为呼叫动作&#xff0c;你也可以设置为其他动…